diff --git a/src/docbkx/reference/jpa.xml b/src/docbkx/reference/jpa.xml index bbfb65264..e57e547b7 100644 --- a/src/docbkx/reference/jpa.xml +++ b/src/docbkx/reference/jpa.xml @@ -92,6 +92,66 @@ + +
+ Annotation based configuration + + The Spring Data JPA repositories support cannot only be activated + through an XML namespace but also using an annotation through + JavaConfig. + + + Spring Data JPA repositories using JavaConfig + + @Configuration +@EnableJpaRepositories +@EnableTransactionManagement +class ApplicationConfig { + + @Bean + public DataSource dataSource() { + + EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder(); + return builder.setType(EmbeddedDatabaseType.HSQL).build(); + } + + @Bean + public EntityManagerFactory entityManagerFactory() { + + HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); + vendorAdapter.setGenerateDdl(true); + + LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean(); + factory.setJpaVendorAdapter(vendorAdapter); + factory.setPackagesToScan("com.acme.domain"); + factory.setDataSource(dataSource()); + factory.afterPropertiesSet(); + + return factory.getObject(); + } + + @Bean + public PlatformTransactionManager transactionManager() { + + JpaTransactionManager txManager = new JpaTransactionManager(); + txManager.setEntityManagerFactory(entityManagerFactory()); + return txManager; + } +} + + + The just shown configuration class sets up an embedded HSQL + database using the EmbeddedDatabaseBuilder API of + spring-jdbc. We then set up a + EntityManagerFactory and use Hibernate as + sample persistence provider. The last infrastructure component declared + here is the JpaTransactionManager. We eventually + activate Spring Data JPA repositories using the + @EnableJpaRepositories annotation which + essentially carries the same attributes as the XML namespace does. If no + base package is configured it will use the one the configuration class + resides in. +
@@ -570,7 +630,7 @@ int setFixedFirstnameFor(String firstname, String lastname); Specifications in a variety of ways. For example, the readAll method will return all - entities that match the specification: + entities that match the specification: List<T> readAll(Specification<T> spec); diff --git a/src/main/java/org/springframework/data/jpa/repository/config/EnableJpaRepositories.java b/src/main/java/org/springframework/data/jpa/repository/config/EnableJpaRepositories.java new file mode 100644 index 000000000..95060794c --- /dev/null +++ b/src/main/java/org/springframework/data/jpa/repository/config/EnableJpaRepositories.java @@ -0,0 +1,125 @@ +/* + * Copyright 2012 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.jpa.repository.config; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import javax.persistence.EntityManagerFactory; + +import org.springframework.beans.factory.FactoryBean; +import org.springframework.context.annotation.ComponentScan.Filter; +import org.springframework.context.annotation.Import; +import org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean; +import org.springframework.data.repository.query.QueryLookupStrategy; +import org.springframework.data.repository.query.QueryLookupStrategy.Key; +import org.springframework.transaction.PlatformTransactionManager; + +/** + * Annotation to enable JPA repositories. Will scan the package of the annotated configuration class for Spring Data + * repositories by default. + * + * @author Oliver Gierke + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Import(JpaRepositoriesRegistrar.class) +public @interface EnableJpaRepositories { + + /** + * Alias for the {@link #basePackages()} attribute. Allows for more concise annotation declarations e.g.: + * {@code @EnableJpaRepositories("org.my.pkg")} instead of {@code @EnableJpaRepositories(basePackages="org.my.pkg")}. + */ + String[] value() default {}; + + /** + * Base packages to scan for annotated components. {@link #value()} is an alias for (and mutually exclusive with) this + * attribute. Use {@link #basePackageClasses()} for a type-safe alternative to String-based package names. + */ + String[] basePackages() default {}; + + /** + * Type-safe alternative to {@link #basePackages()} for specifying the packages to scan for annotated components. The + * package of each class specified will be scanned. Consider creating a special no-op marker class or interface in + * each package that serves no purpose other than being referenced by this attribute. + */ + Class[] basePackageClasses() default {}; + + /** + * Specifies which types are eligible for component scanning. Further narrows the set of candidate components from + * everything in {@link #basePackages()} to everything in the base packages that matches the given filter or filters. + */ + Filter[] includeFilters() default {}; + + /** + * Specifies which types are not eligible for component scanning. + */ + Filter[] excludeFilters() default {}; + + /** + * Returns the postfix to be used when looking up custom repository implementations. Defaults to {@literal Impl}. So + * for a repository named {@code PersonRepository} the corresponding implementation class will be looked up scanning + * for {@code PersonRepositoryImpl}. + * + * @return + */ + String repositoryImplementationPostfix() default "Impl"; + + /** + * Configures the location of where to find the Spring Data named queries properties file. Will default to + * {@code META-INFO/jpa-named-queries.properties}. + * + * @return + */ + String namedQueriesLocation() default ""; + + /** + * Returns the key of the {@link QueryLookupStrategy} to be used for lookup queries for query methods. Defaults to + * {@link Key#CREATE_IF_NOT_FOUND}. + * + * @return + */ + Key queryLookupStrategy() default Key.CREATE_IF_NOT_FOUND; + + /** + * Returns the {@link FactoryBean} class to be used for each repository instance. Defaults to + * {@link JpaRepositoryFactoryBean}. + * + * @return + */ + Class repositoryFactoryBeanClass() default JpaRepositoryFactoryBean.class; + + // JPA sepcific configuration + /** + * Configures the name of the {@link EntityManagerFactory} bean definition to be used to create repositories + * discovered through this annotation. Defaults to {@code entityManagerFactory}. + * + * @return + */ + String entityManagerFactoryRef() default "entityManagerFactory"; + + /** + * /** Configures the name of the {@link PlatformTransactionManager} bean definition to be used to create repositories + * discovered through this annotation. Defaults to {@code transactionManager}. + * + * @return + */ + String transactionManagerRef() default "transactionManager"; +} diff --git a/src/main/java/org/springframework/data/jpa/repository/config/JpaRepositoriesRegistrar.java b/src/main/java/org/springframework/data/jpa/repository/config/JpaRepositoriesRegistrar.java new file mode 100644 index 000000000..4f8619328 --- /dev/null +++ b/src/main/java/org/springframework/data/jpa/repository/config/JpaRepositoriesRegistrar.java @@ -0,0 +1,48 @@ +/* + * Copyright 2012 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.jpa.repository.config; + +import java.lang.annotation.Annotation; + +import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; +import org.springframework.data.repository.config.RepositoryBeanDefinitionRegistrarSupport; +import org.springframework.data.repository.config.RepositoryConfigurationExtension; + +/** + * {@link ImportBeanDefinitionRegistrar} to enable {@link EnableJpaRepositories} annotation. + * + * @author Oliver Gierke + */ +class JpaRepositoriesRegistrar extends RepositoryBeanDefinitionRegistrarSupport { + + /* + * (non-Javadoc) + * @see org.springframework.data.repository.config.RepositoryBeanDefinitionRegistrarSupport#getAnnotation() + */ + @Override + protected Class getAnnotation() { + return EnableJpaRepositories.class; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.repository.config.RepositoryBeanDefinitionRegistrarSupport#getExtension() + */ + @Override + protected RepositoryConfigurationExtension getExtension() { + return new JpaRepositoryConfigExtension(); + } +} diff --git a/src/main/java/org/springframework/data/jpa/repository/config/JpaRepositoryConfigDefinitionParser.java b/src/main/java/org/springframework/data/jpa/repository/config/JpaRepositoryConfigDefinitionParser.java deleted file mode 100644 index cb66e42ea..000000000 --- a/src/main/java/org/springframework/data/jpa/repository/config/JpaRepositoryConfigDefinitionParser.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright 2008-2011 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.data.jpa.repository.config; - -import org.springframework.beans.factory.config.BeanDefinition; -import org.springframework.beans.factory.support.AbstractBeanDefinition; -import org.springframework.beans.factory.support.BeanDefinitionBuilder; -import org.springframework.beans.factory.support.BeanDefinitionRegistry; -import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor; -import org.springframework.data.jpa.repository.config.SimpleJpaRepositoryConfiguration.JpaRepositoryConfiguration; -import org.springframework.data.repository.config.AbstractRepositoryConfigDefinitionParser; -import org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor; -import org.springframework.util.StringUtils; -import org.w3c.dom.Element; - -/** - * Parser to create bean definitions for repositories namespace. Registers bean definitions for repositories as well as - * {@code PersistenceAnnotationBeanPostProcessor} and {@code PersistenceExceptionTranslationPostProcessor} to - * transparently inject entity manager factory instance and apply exception translation. - *

- * The definition parser allows two ways of configuration. Either it looks up the manually defined repository instances - * or scans the defined domain package for candidates for repositories. - * - * @author Oliver Gierke - * @author Eberhard Wolff - * @author Gil Markham - */ -class JpaRepositoryConfigDefinitionParser extends - AbstractRepositoryConfigDefinitionParser { - - private static final Class PAB_POST_PROCESSOR = PersistenceAnnotationBeanPostProcessor.class; - private static final Class PET_POST_PROCESSOR = PersistenceExceptionTranslationPostProcessor.class; - private static final String DEFAULT_TRANSACTION_MANAGER_BEAN_NAME = "transactionManager"; - - /* - * (non-Javadoc) - * @see org.springframework.data.repository.config.AbstractRepositoryConfigDefinitionParser#getGlobalRepositoryConfigInformation(org.w3c.dom.Element) - */ - @Override - protected SimpleJpaRepositoryConfiguration getGlobalRepositoryConfigInformation(Element element) { - - return new SimpleJpaRepositoryConfiguration(element); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.repository.config.AbstractRepositoryConfigDefinitionParser#postProcessBeanDefinition(org.springframework.data.repository.config.SingleRepositoryConfigInformation, org.springframework.beans.factory.support.BeanDefinitionBuilder, org.springframework.beans.factory.support.BeanDefinitionRegistry, java.lang.Object) - */ - @Override - protected void postProcessBeanDefinition(JpaRepositoryConfiguration ctx, BeanDefinitionBuilder builder, - BeanDefinitionRegistry registry, Object beanSource) { - - String transactionManagerRef = StringUtils.hasText(ctx.getTransactionManagerRef()) ? ctx.getTransactionManagerRef() - : DEFAULT_TRANSACTION_MANAGER_BEAN_NAME; - builder.addPropertyValue("transactionManager", transactionManagerRef); - - String entityManagerRef = ctx.getEntityManagerFactoryRef(); - - if (StringUtils.hasText(entityManagerRef)) { - builder.addPropertyValue("entityManager", getEntityManagerBeanDefinitionFor(entityManagerRef, beanSource)); - } - } - - /** - * Creates an anonymous factory to extract the actual {@link javax.persistence.EntityManager} from the - * {@link javax.persistence.EntityManagerFactory} bean name reference. - * - * @param entityManagerFactoryBeanName - * @param source - * @return - */ - private BeanDefinition getEntityManagerBeanDefinitionFor(String entityManagerFactoryBeanName, Object source) { - - BeanDefinitionBuilder builder = BeanDefinitionBuilder - .rootBeanDefinition("org.springframework.orm.jpa.SharedEntityManagerCreator"); - builder.setFactoryMethod("createSharedEntityManager"); - builder.addConstructorArgReference(entityManagerFactoryBeanName); - - AbstractBeanDefinition bean = builder.getRawBeanDefinition(); - bean.setSource(source); - - return bean; - } - - /** - * Registers an additional {@link org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor} to - * trigger automatic injextion of {@link javax.persistence.EntityManager} . - * - * @param registry - * @param source - */ - @Override - protected void registerBeansForRoot(BeanDefinitionRegistry registry, Object source) { - - super.registerBeansForRoot(registry, source); - - if (!hasBean(PET_POST_PROCESSOR, registry)) { - - AbstractBeanDefinition definition = BeanDefinitionBuilder.rootBeanDefinition(PET_POST_PROCESSOR) - .getBeanDefinition(); - - registerWithSourceAndGeneratedBeanName(registry, definition, source); - } - - if (!hasBean(PAB_POST_PROCESSOR, registry)) { - - AbstractBeanDefinition definition = BeanDefinitionBuilder.rootBeanDefinition(PAB_POST_PROCESSOR) - .getBeanDefinition(); - - registerWithSourceAndGeneratedBeanName(registry, definition, source); - } - } -} diff --git a/src/main/java/org/springframework/data/jpa/repository/config/JpaRepositoryConfigExtension.java b/src/main/java/org/springframework/data/jpa/repository/config/JpaRepositoryConfigExtension.java new file mode 100644 index 000000000..df40eb780 --- /dev/null +++ b/src/main/java/org/springframework/data/jpa/repository/config/JpaRepositoryConfigExtension.java @@ -0,0 +1,156 @@ +/* + * Copyright 2012 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.jpa.repository.config; + +import javax.persistence.PersistenceContext; +import javax.persistence.PersistenceUnit; + +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.support.AbstractBeanDefinition; +import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.core.annotation.AnnotationAttributes; +import org.springframework.dao.DataAccessException; +import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor; +import org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean; +import org.springframework.data.repository.config.AnnotationRepositoryConfigurationSource; +import org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport; +import org.springframework.data.repository.config.RepositoryConfigurationSource; +import org.springframework.data.repository.config.XmlRepositoryConfigurationSource; +import org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor; +import org.springframework.util.StringUtils; +import org.w3c.dom.Element; + +/** + * JPA specific configuration extension parsing custom attributes from the XML namespace and + * {@link EnableJpaRepositories} annotation. Also, it registers bean definitions for a + * {@link PersistenceAnnotationBeanPostProcessor} (to trigger injection into {@link PersistenceContext}/ + * {@link PersistenceUnit} annotated properties and methods) as well as + * {@link PersistenceExceptionTranslationPostProcessor} to enable exception translation of persistence specific + * exceptions into Spring's {@link DataAccessException} hierarchy. + * + * @author Oliver Gierke + * @author Eberhard Wolff + * @author Gil Markham + */ +public class JpaRepositoryConfigExtension extends RepositoryConfigurationExtensionSupport { + + private static final Class PAB_POST_PROCESSOR = PersistenceAnnotationBeanPostProcessor.class; + private static final Class PET_POST_PROCESSOR = PersistenceExceptionTranslationPostProcessor.class; + private static final String DEFAULT_TRANSACTION_MANAGER_BEAN_NAME = "transactionManager"; + + /* + * (non-Javadoc) + * @see org.springframework.data.repository.config14.RepositoryConfigurationExtension#getRepositoryInterface() + */ + public String getRepositoryFactoryClassName() { + return JpaRepositoryFactoryBean.class.getName(); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.repository.config14.RepositoryConfigurationExtensionSupport#getModulePrefix() + */ + @Override + protected String getModulePrefix() { + return "jpa"; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.repository.config14.RepositoryConfigurationExtensionSupport#postProcess(org.springframework.beans.factory.support.BeanDefinitionBuilder, org.springframework.data.repository.config14.XmlRepositoryConfigurationSource) + */ + @Override + public void postProcess(BeanDefinitionBuilder builder, XmlRepositoryConfigurationSource config) { + + Element element = config.getElement(); + + postProcess(builder, element.getAttribute("transaction-manager-ref"), + element.getAttribute("entity-manager-factory-ref"), config.getSource()); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport#postProcess(org.springframework.beans.factory.support.BeanDefinitionBuilder, org.springframework.data.repository.config.AnnotationRepositoryConfigurationSource) + */ + @Override + public void postProcess(BeanDefinitionBuilder builder, AnnotationRepositoryConfigurationSource config) { + + AnnotationAttributes attributes = config.getAttributes(); + + postProcess(builder, attributes.getString("transactionManagerRef"), + attributes.getString("entityManagerFactoryRef"), config.getSource()); + } + + private void postProcess(BeanDefinitionBuilder builder, String transactionManagerRef, String entityManagerRef, + Object source) { + + transactionManagerRef = StringUtils.hasText(transactionManagerRef) ? transactionManagerRef + : DEFAULT_TRANSACTION_MANAGER_BEAN_NAME; + builder.addPropertyValue("transactionManager", transactionManagerRef); + + if (StringUtils.hasText(entityManagerRef)) { + builder.addPropertyValue("entityManager", getEntityManagerBeanDefinitionFor(entityManagerRef, source)); + } + } + + /** + * Creates an anonymous factory to extract the actual {@link javax.persistence.EntityManager} from the + * {@link javax.persistence.EntityManagerFactory} bean name reference. + * + * @param entityManagerFactoryBeanName + * @param source + * @return + */ + private BeanDefinition getEntityManagerBeanDefinitionFor(String entityManagerFactoryBeanName, Object source) { + + BeanDefinitionBuilder builder = BeanDefinitionBuilder + .rootBeanDefinition("org.springframework.orm.jpa.SharedEntityManagerCreator"); + builder.setFactoryMethod("createSharedEntityManager"); + builder.addConstructorArgReference(entityManagerFactoryBeanName); + + AbstractBeanDefinition bean = builder.getRawBeanDefinition(); + bean.setSource(source); + + return bean; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport#registerBeansForRoot(org.springframework.beans.factory.support.BeanDefinitionRegistry, org.springframework.data.repository.config.RepositoryConfigurationSource) + */ + @Override + public void registerBeansForRoot(BeanDefinitionRegistry registry, RepositoryConfigurationSource configurationSource) { + + super.registerBeansForRoot(registry, configurationSource); + + if (!hasBean(PET_POST_PROCESSOR, registry)) { + + AbstractBeanDefinition definition = BeanDefinitionBuilder.rootBeanDefinition(PET_POST_PROCESSOR) + .getBeanDefinition(); + + registerWithSourceAndGeneratedBeanName(registry, definition, configurationSource.getSource()); + } + + if (!hasBean(PAB_POST_PROCESSOR, registry)) { + + AbstractBeanDefinition definition = BeanDefinitionBuilder.rootBeanDefinition(PAB_POST_PROCESSOR) + .getBeanDefinition(); + + registerWithSourceAndGeneratedBeanName(registry, definition, configurationSource.getSource()); + } + } +} diff --git a/src/main/java/org/springframework/data/jpa/repository/config/JpaRepositoryNameSpaceHandler.java b/src/main/java/org/springframework/data/jpa/repository/config/JpaRepositoryNameSpaceHandler.java index 710c618cd..44d27c067 100644 --- a/src/main/java/org/springframework/data/jpa/repository/config/JpaRepositoryNameSpaceHandler.java +++ b/src/main/java/org/springframework/data/jpa/repository/config/JpaRepositoryNameSpaceHandler.java @@ -16,6 +16,8 @@ package org.springframework.data.jpa.repository.config; import org.springframework.beans.factory.xml.NamespaceHandlerSupport; +import org.springframework.data.repository.config.RepositoryBeanDefinitionParser; +import org.springframework.data.repository.config.RepositoryConfigurationExtension; /** * Simple namespace handler for {@literal repositories} namespace. @@ -31,7 +33,10 @@ public class JpaRepositoryNameSpaceHandler extends NamespaceHandlerSupport { */ public void init() { - registerBeanDefinitionParser("repositories", new JpaRepositoryConfigDefinitionParser()); + RepositoryConfigurationExtension extension = new JpaRepositoryConfigExtension(); + RepositoryBeanDefinitionParser repositoryBeanDefinitionParser = new RepositoryBeanDefinitionParser(extension); + + registerBeanDefinitionParser("repositories", repositoryBeanDefinitionParser); registerBeanDefinitionParser("auditing", new AuditingBeanDefinitionParser()); } } diff --git a/src/main/java/org/springframework/data/jpa/repository/config/SimpleJpaRepositoryConfiguration.java b/src/main/java/org/springframework/data/jpa/repository/config/SimpleJpaRepositoryConfiguration.java deleted file mode 100644 index 5597a4bc4..000000000 --- a/src/main/java/org/springframework/data/jpa/repository/config/SimpleJpaRepositoryConfiguration.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright 2008-2011 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.data.jpa.repository.config; - -import org.springframework.data.repository.config.AutomaticRepositoryConfigInformation; -import org.springframework.data.repository.config.ManualRepositoryConfigInformation; -import org.springframework.data.repository.config.RepositoryConfig; -import org.springframework.data.repository.config.SingleRepositoryConfigInformation; -import org.w3c.dom.Element; - -/** - * @author Oliver Gierke - */ -public class SimpleJpaRepositoryConfiguration extends - RepositoryConfig { - - private static final String FACTORY_CLASS = "org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean"; - private static final String ENTITY_MANAGER_FACTORY_REF = "entity-manager-factory-ref"; - - /** - * @param repositoriesElement - */ - public SimpleJpaRepositoryConfiguration(Element repositoriesElement) { - - super(repositoriesElement, FACTORY_CLASS); - } - - /* - * (non-Javadoc) - * - * @see - * org.springframework.data.repository.config.GlobalRepositoryConfigInformation - * #getAutoconfigRepositoryInformation(java.lang.String) - */ - public JpaRepositoryConfiguration getAutoconfigRepositoryInformation(String interfaceName) { - - return new AutomaticJpaRepositoryConfigInformation(interfaceName, this); - } - - /* - * (non-Javadoc) - * - * @see - * org.springframework.data.jpa.repository.config.RepositoryConfigContext - * #getManualRepositoryInformation(org.w3c.dom.Element, - * org.springframework.data - * .jpa.repository.config.CommonRepositoryInformation) - */ - @Override - public JpaRepositoryConfiguration createSingleRepositoryConfigInformationFor(Element element) { - - return new ManualJpaRepositoryConfigInformation(element, this); - } - - /* - * (non-Javadoc) - * - * @see - * org.springframework.data.repository.config.CommonRepositoryConfigInformation - * #getNamedQueriesLocation() - */ - public String getNamedQueriesLocation() { - - return "classpath*:META-INF/jpa-named-queries.properties"; - } - - /** - * Returns the name of the entity manager factory bean. - * - * @return - */ - public String getEntityManagerFactoryRef() { - - return getSource().getAttribute(ENTITY_MANAGER_FACTORY_REF); - } - - private static class AutomaticJpaRepositoryConfigInformation extends - AutomaticRepositoryConfigInformation implements JpaRepositoryConfiguration { - - public AutomaticJpaRepositoryConfigInformation(String interfaceName, SimpleJpaRepositoryConfiguration parent) { - - super(interfaceName, parent); - } - - /** - * Returns the {@link javax.persistence.EntityManagerFactory} reference to be used for all the repository instances - * configured. - * - * @return - */ - public String getEntityManagerFactoryRef() { - - return getParent().getEntityManagerFactoryRef(); - } - } - - private static class ManualJpaRepositoryConfigInformation extends - ManualRepositoryConfigInformation implements JpaRepositoryConfiguration { - - public ManualJpaRepositoryConfigInformation(Element element, SimpleJpaRepositoryConfiguration parent) { - - super(element, parent); - } - - /* - * (non-Javadoc) - * - * @see org.springframework.data.jpa.repository.config. - * SimpleJpaRepositoryConfiguration - * .JpaRepositoryConfiguration#getEntityManagerFactoryRef() - */ - public String getEntityManagerFactoryRef() { - - return getAttribute(ENTITY_MANAGER_FACTORY_REF); - } - } - - interface JpaRepositoryConfiguration extends SingleRepositoryConfigInformation { - - String getEntityManagerFactoryRef(); - } -} diff --git a/src/main/resources/META-INF/spring.schemas b/src/main/resources/META-INF/spring.schemas index 6cb49ba70..e09b4307a 100644 --- a/src/main/resources/META-INF/spring.schemas +++ b/src/main/resources/META-INF/spring.schemas @@ -1,3 +1,4 @@ http\://www.springframework.org/schema/data/jpa/spring-jpa-1.0.xsd=org/springframework/data/jpa/repository/config/spring-jpa-1.0.xsd http\://www.springframework.org/schema/data/jpa/spring-jpa-1.1.xsd=org/springframework/data/jpa/repository/config/spring-jpa-1.1.xsd -http\://www.springframework.org/schema/data/jpa/spring-jpa.xsd=org/springframework/data/jpa/repository/config/spring-jpa-1.1.xsd +http\://www.springframework.org/schema/data/jpa/spring-jpa-1.2.xsd=org/springframework/data/jpa/repository/config/spring-jpa-1.2.xsd +http\://www.springframework.org/schema/data/jpa/spring-jpa.xsd=org/springframework/data/jpa/repository/config/spring-jpa-1.2.xsd diff --git a/src/main/resources/org/springframework/data/jpa/repository/config/spring-jpa-1.2.xsd b/src/main/resources/org/springframework/data/jpa/repository/config/spring-jpa-1.2.xsd new file mode 100644 index 000000000..8aebea806 --- /dev/null +++ b/src/main/resources/org/springframework/data/jpa/repository/config/spring-jpa-1.2.xsd @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/java/org/springframework/data/jpa/repository/UserRepositoryTests.java b/src/test/java/org/springframework/data/jpa/repository/UserRepositoryTests.java index 9febfafbf..b4de92d66 100644 --- a/src/test/java/org/springframework/data/jpa/repository/UserRepositoryTests.java +++ b/src/test/java/org/springframework/data/jpa/repository/UserRepositoryTests.java @@ -61,7 +61,7 @@ import org.springframework.transaction.annotation.Transactional; * @author Oliver Gierke */ @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = { "classpath:application-context.xml" }) +@ContextConfiguration("classpath:application-context.xml") @Transactional public class UserRepositoryTests { @@ -889,6 +889,18 @@ public class UserRepositoryTests { assertThat(repository.count(), is(count)); } + @Test + public void ordersByReferencedEntityCorrectly() { + + flushTestUsers(); + firstUser.setManager(thirdUser); + repository.save(firstUser); + + Page all = repository.findAll(new PageRequest(0, 10, new Sort("manager.id"))); + + assertThat(all.getContent().isEmpty(), is(false)); + } + private Page executeSpecWithSort(Sort sort) { flushTestUsers(); diff --git a/src/test/java/org/springframework/data/jpa/repository/config/JpaRepositoriesRegistrarIntegrationTests.java b/src/test/java/org/springframework/data/jpa/repository/config/JpaRepositoriesRegistrarIntegrationTests.java new file mode 100644 index 000000000..92cdc639c --- /dev/null +++ b/src/test/java/org/springframework/data/jpa/repository/config/JpaRepositoriesRegistrarIntegrationTests.java @@ -0,0 +1,83 @@ +/* + * Copyright 2012 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.jpa.repository.config; + +import javax.persistence.EntityManagerFactory; +import javax.sql.DataSource; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.jpa.repository.sample.UserRepository; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; +import org.springframework.orm.jpa.JpaDialect; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.orm.jpa.vendor.HibernateJpaDialect; +import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.transaction.PlatformTransactionManager; + +/** + * Integration test for {@link JpaRepositoriesRegistrar}. + * + * @author Oliver Gierke + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration +public class JpaRepositoriesRegistrarIntegrationTests { + + @Autowired + UserRepository repository; + + @Configuration + @EnableJpaRepositories(basePackages = "org.springframework.data.jpa.repository.sample") + static class Config { + + @Bean + public DataSource dataSource() { + return new EmbeddedDatabaseBuilder().build(); + } + + @Bean + public EntityManagerFactory entityManagerFactory() { + LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean(); + factory.setDataSource(dataSource()); + factory.setPersistenceUnitName("default"); + factory.setJpaVendorAdapter(new HibernateJpaVendorAdapter()); + factory.afterPropertiesSet(); + return factory.getObject(); + } + + @Bean + public JpaDialect jpaDialect() { + return new HibernateJpaDialect(); + } + + @Bean + public PlatformTransactionManager transactionManager() { + return new JpaTransactionManager(entityManagerFactory()); + } + } + + @Test + public void foo() { + + } +} diff --git a/src/test/java/org/springframework/data/jpa/repository/config/JpaRepositoriesRegistrarUnitTests.java b/src/test/java/org/springframework/data/jpa/repository/config/JpaRepositoriesRegistrarUnitTests.java new file mode 100644 index 000000000..71f411eb5 --- /dev/null +++ b/src/test/java/org/springframework/data/jpa/repository/config/JpaRepositoriesRegistrarUnitTests.java @@ -0,0 +1,63 @@ +/* + * Copyright 2012 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.jpa.repository.config; + +import static org.hamcrest.CoreMatchers.*; +import static org.junit.Assert.*; + +import java.util.Arrays; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.beans.factory.support.DefaultListableBeanFactory; +import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; +import org.springframework.core.type.AnnotationMetadata; +import org.springframework.core.type.StandardAnnotationMetadata; +import org.springframework.data.jpa.repository.sample.UserRepository; + +/** + * Unit test for {@link JpaRepositoriesRegistrar}. + * + * @author Oliver Gierke + */ +public class JpaRepositoriesRegistrarUnitTests { + + BeanDefinitionRegistry registry; + AnnotationMetadata metadata; + + @Before + public void setUp() { + + metadata = new StandardAnnotationMetadata(Config.class, true); + registry = new DefaultListableBeanFactory(); + } + + @Test + public void configuresRepositoriesCorrectly() { + + ImportBeanDefinitionRegistrar registrar = new JpaRepositoriesRegistrar(); + registrar.registerBeanDefinitions(metadata, registry); + + Iterable names = Arrays.asList(registry.getBeanDefinitionNames()); + assertThat(names, hasItems("userRepository", "auditableUserRepository", "roleRepository")); + } + + @EnableJpaRepositories(basePackageClasses = UserRepository.class) + class Config { + + } +} diff --git a/src/test/resources/auditing/auditing-bfpp-context.xml b/src/test/resources/auditing/auditing-bfpp-context.xml index fb81c5161..f9bae7103 100644 --- a/src/test/resources/auditing/auditing-bfpp-context.xml +++ b/src/test/resources/auditing/auditing-bfpp-context.xml @@ -5,7 +5,7 @@ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd" default-lazy-init="true"> - + diff --git a/src/test/resources/auditing/auditing-entity-listener.xml b/src/test/resources/auditing/auditing-entity-listener.xml index 592befe3c..849f3bc7a 100644 --- a/src/test/resources/auditing/auditing-entity-listener.xml +++ b/src/test/resources/auditing/auditing-entity-listener.xml @@ -3,21 +3,18 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jpa="http://www.springframework.org/schema/data/jpa" xmlns:context="http://www.springframework.org/schema/context" - xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd - http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.0.xsd - http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> + xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd + http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> - - - - + diff --git a/src/test/resources/config/lookup-strategies-context.xml b/src/test/resources/config/lookup-strategies-context.xml index 2ada6e239..dbfa58d41 100644 --- a/src/test/resources/config/lookup-strategies-context.xml +++ b/src/test/resources/config/lookup-strategies-context.xml @@ -7,8 +7,6 @@ - - - + diff --git a/src/test/resources/config/namespace-application-context.xml b/src/test/resources/config/namespace-application-context.xml index 46b23fff0..a49341a88 100644 --- a/src/test/resources/config/namespace-application-context.xml +++ b/src/test/resources/config/namespace-application-context.xml @@ -23,11 +23,7 @@ ! do not have to be explicitly registered as they are included by namespace parser ! --> - - - - - + diff --git a/src/test/resources/multiple-entity-manager-context.xml b/src/test/resources/multiple-entity-manager-context.xml index 916e4a036..838bea4ce 100644 --- a/src/test/resources/multiple-entity-manager-context.xml +++ b/src/test/resources/multiple-entity-manager-context.xml @@ -3,8 +3,11 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jpa="http://www.springframework.org/schema/data/jpa" xmlns:repository="http://www.springframework.org/schema/data/repository" - xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd - http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd"> + xmlns:context="http://www.springframework.org/schema/context" + xsi:schemaLocation="http://www.springframework.org/schema/data/repository http://www.springframework.org/schema/data/repository/spring-repository.xsd + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd + http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> @@ -15,7 +18,7 @@ - + diff --git a/src/test/resources/multiple-entity-manager-integration-context.xml b/src/test/resources/multiple-entity-manager-integration-context.xml index 01287bb26..f2d7b5d37 100644 --- a/src/test/resources/multiple-entity-manager-integration-context.xml +++ b/src/test/resources/multiple-entity-manager-integration-context.xml @@ -2,8 +2,10 @@ @@ -39,14 +41,13 @@ - - + - +