diff --git a/README.adoc b/README.adoc index a9ed87f..444ae85 100644 --- a/README.adoc +++ b/README.adoc @@ -3,7 +3,7 @@ image:https://spring.io/badges/spring-data-envers/snapshot.svg[title=Spring Data = Spring Data Envers image:https://jenkins.spring.io/buildStatus/icon?job=spring-data-envers%2Fmaster&subject=Build[link=https://jenkins.spring.io/view/SpringData/job/spring-data-envers/] https://gitter.im/spring-projects/spring-data[image:https://badges.gitter.im/spring-projects/spring-data.svg[Gitter]] -This project is an extension of the https://github.com/SpringSource/spring-data-jpa[Spring Data JPA] project to allow access to entity revisions managed by Hibernate Envers. The sources mostly originate from a contribution of Philipp Hügelmeyer https://github.com/hygl[@hygl]. +This project is an extension of the https://github.com/SpringSource/spring-data-jpa[Spring Data JPA] project to allow access to entity revisions managed by Hibernate Envers.The sources mostly originate from a contribution of Philipp Hügelmeyer https://github.com/hygl[@hygl]. The core feature of the module consists of an implementation of the `RevisionRepository` of Spring Data Commons. @@ -35,12 +35,12 @@ interface PersonRepository extends RevisionRepository, Cr } ---- -To successfully activate the Spring Data Envers repository factory, use the Spring Data JPA's `@EnableJpaRepositories` annotation, specifying the `repositoryFactoryBeanClass` attribute: +To activate the Spring Data Envers repositories, use the Spring Data Envers' `EnableEnversRepositories` annotation: [source,java] ---- @Configuration -@EnableJpaRepositories(repositoryFactoryBeanClass = EnversRevisionRepositoryFactoryBean.class) +@EnableEnversRepositories public class ApplicationConfiguration { // Your configuration beans diff --git a/src/main/asciidoc/envers.adoc b/src/main/asciidoc/envers.adoc index fa4feb2..534ae9c 100644 --- a/src/main/asciidoc/envers.adoc +++ b/src/main/asciidoc/envers.adoc @@ -40,7 +40,7 @@ To enable Spring Data Envers and Spring Data JPA, we need to configure two beans [source,java] ---- @Configuration -@EnableJpaRepositories(repositoryFactoryBeanClass = EnversRevisionRepositoryFactoryBean.class) // <1> +@EnableEnversRepositories @EnableTransactionManagement public class EnversDemoConfiguration { @@ -73,7 +73,6 @@ public class EnversDemoConfiguration { } } ---- -<1> This is the only difference from a normal Spring Data JPA configuration. `EnversRevisionRepositoryFactoryBean` ensures implementations of the methods in `RevisionRepository` are available. ==== To actually use Spring Data Envers, make one or more repositories into a {spring-data-commons-javadoc-base}/org/springframework/data/repository/history/RevisionRepository.html[`RevisionRepository`] by adding it as an extended interface: diff --git a/src/main/asciidoc/index.adoc b/src/main/asciidoc/index.adoc index a47a802..0bd9e68 100644 --- a/src/main/asciidoc/index.adoc +++ b/src/main/asciidoc/index.adoc @@ -1,5 +1,5 @@ = Spring Data Envers - Reference Documentation -Oliver Gierke; Jens Schauder +Oliver Gierke; Jens Schauder; Mark Paluch :revnumber: {version} :revdate: {localdate} :javadoc-base: https://docs.spring.io/spring-data/envers/docs/{revnumber}/api/ diff --git a/src/main/java/org/springframework/data/envers/repository/config/EnableEnversRepositories.java b/src/main/java/org/springframework/data/envers/repository/config/EnableEnversRepositories.java new file mode 100644 index 0000000..18c078a --- /dev/null +++ b/src/main/java/org/springframework/data/envers/repository/config/EnableEnversRepositories.java @@ -0,0 +1,199 @@ +/* + * Copyright 2021 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 + * + * https://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.envers.repository.config; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +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.Lazy; +import org.springframework.core.annotation.AliasFor; +import org.springframework.data.envers.repository.support.EnversRevisionRepositoryFactoryBean; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean; +import org.springframework.data.repository.config.BootstrapMode; +import org.springframework.data.repository.config.DefaultRepositoryBaseClass; +import org.springframework.data.repository.query.QueryLookupStrategy; +import org.springframework.data.repository.query.QueryLookupStrategy.Key; +import org.springframework.transaction.PlatformTransactionManager; + +/** + * Annotation to enable Envers repositories. Will scan the package of the annotated configuration class for Spring Data + * repositories by default. + *

+ * This annotation is a meta-annotation for {@link EnableJpaRepositories @EnableJpaRepositories} overriding the default + * {@link #repositoryFactoryBeanClass} to {@link EnversRevisionRepositoryFactoryBean}. + * + * @author Mark Paluch + * @since 2.5 + * @see EnableJpaRepositories + * @see AliasFor + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Inherited +@EnableJpaRepositories +public @interface EnableEnversRepositories { + + /** + * Alias for the {@link #basePackages()} attribute. Allows for more concise annotation declarations e.g.: + * {@code @EnableJpaRepositories("org.my.pkg")} instead of + * {@code @EnableEnversRepositories(basePackages="org.my.pkg")}. + */ + @AliasFor(annotation = EnableJpaRepositories.class) + 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. + */ + @AliasFor(annotation = EnableJpaRepositories.class) + 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. + */ + @AliasFor(annotation = EnableJpaRepositories.class) + 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. + */ + @AliasFor(annotation = EnableJpaRepositories.class) + Filter[] includeFilters() default {}; + + /** + * Specifies which types are not eligible for component scanning. + */ + @AliasFor(annotation = EnableJpaRepositories.class) + 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 + */ + @AliasFor(annotation = EnableJpaRepositories.class) + String repositoryImplementationPostfix() default "Impl"; + + /** + * Configures the location of where to find the Spring Data named queries properties file. Will default to + * {@code META-INF/jpa-named-queries.properties}. + * + * @return + */ + @AliasFor(annotation = EnableJpaRepositories.class) + 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 + */ + @AliasFor(annotation = EnableJpaRepositories.class) + 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 + */ + @AliasFor(annotation = EnableJpaRepositories.class) + Class repositoryFactoryBeanClass() default EnversRevisionRepositoryFactoryBean.class; + + /** + * Configure the repository base class to be used to create repository proxies for this particular configuration. + * + * @return + */ + @AliasFor(annotation = EnableJpaRepositories.class) + Class repositoryBaseClass() default DefaultRepositoryBaseClass.class; + + // JPA specific 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 + */ + @AliasFor(annotation = EnableJpaRepositories.class) + 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 + */ + @AliasFor(annotation = EnableJpaRepositories.class) + String transactionManagerRef() default "transactionManager"; + + /** + * Configures whether nested repository-interfaces (e.g. defined as inner classes) should be discovered by the + * repositories infrastructure. + */ + @AliasFor(annotation = EnableJpaRepositories.class) + boolean considerNestedRepositories() default false; + + /** + * Configures whether to enable default transactions for Spring Data JPA repositories. Defaults to {@literal true}. If + * disabled, repositories must be used behind a facade that's configuring transactions (e.g. using Spring's annotation + * driven transaction facilities) or repository methods have to be used to demarcate transactions. + * + * @return whether to enable default transactions, defaults to {@literal true}. + */ + @AliasFor(annotation = EnableJpaRepositories.class) + boolean enableDefaultTransactions() default true; + + /** + * Configures when the repositories are initialized in the bootstrap lifecycle. {@link BootstrapMode#DEFAULT} + * (default) means eager initialization except all repository interfaces annotated with {@link Lazy}, + * {@link BootstrapMode#LAZY} means lazy by default including injection of lazy-initialization proxies into client + * beans so that those can be instantiated but will only trigger the initialization upon first repository usage (i.e a + * method invocation on it). This means repositories can still be uninitialized when the application context has + * completed its bootstrap. {@link BootstrapMode#DEFERRED} is fundamentally the same as {@link BootstrapMode#LAZY}, + * but triggers repository initialization when the application context finishes its bootstrap. + * + * @return + */ + @AliasFor(annotation = EnableJpaRepositories.class) + BootstrapMode bootstrapMode() default BootstrapMode.DEFAULT; + + /** + * Configures what character is used to escape the wildcards {@literal _} and {@literal %} in derived queries with + * {@literal contains}, {@literal startsWith} or {@literal endsWith} clauses. + * + * @return a single character used for escaping. + */ + @AliasFor(annotation = EnableJpaRepositories.class) + char escapeCharacter() default '\\'; +} diff --git a/src/main/java/org/springframework/data/envers/repository/config/package-info.java b/src/main/java/org/springframework/data/envers/repository/config/package-info.java new file mode 100644 index 0000000..2e79b25 --- /dev/null +++ b/src/main/java/org/springframework/data/envers/repository/config/package-info.java @@ -0,0 +1,5 @@ +/** + * Classes for Envers Repositories configuration support. + */ +@org.springframework.lang.NonNullApi +package org.springframework.data.envers.repository.config; diff --git a/src/test/java/org/springframework/data/envers/Config.java b/src/test/java/org/springframework/data/envers/Config.java index a4c4dcb..93ad2f5 100755 --- a/src/test/java/org/springframework/data/envers/Config.java +++ b/src/test/java/org/springframework/data/envers/Config.java @@ -22,10 +22,10 @@ import java.util.Map; import javax.sql.DataSource; import org.hibernate.envers.strategy.ValidityAuditStrategy; + import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.data.envers.repository.support.EnversRevisionRepositoryFactoryBean; -import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.data.envers.repository.config.EnableEnversRepositories; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; import org.springframework.orm.jpa.AbstractEntityManagerFactoryBean; @@ -41,7 +41,7 @@ import org.springframework.transaction.PlatformTransactionManager; * @author Oliver Gierke */ @Configuration -@EnableJpaRepositories(repositoryFactoryBeanClass = EnversRevisionRepositoryFactoryBean.class) +@EnableEnversRepositories public class Config { @Bean