From b47a340c0d88660a69994e699c30cd61b6c5529c Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 22 Aug 2023 14:52:18 +0200 Subject: [PATCH] Restructure content to include partials from Commons. See #3080 --- spring-data-jpa-distribution/pom.xml | 26 +-- src/main/antora/antora-playbook.yml | 5 + src/main/antora/modules/ROOT/nav.adoc | 27 ++- .../ROOT/pages/{jpa => }/auditing.adoc | 6 +- .../modules/ROOT/pages/commons/upgrade.adoc | 1 + .../antora/modules/ROOT/pages/envers.adoc | 205 +----------------- .../ROOT/pages/envers/configuration.adoc | 95 ++++++++ .../ROOT/pages/envers/introduction.adoc | 14 ++ .../modules/ROOT/pages/envers/usage.adoc | 93 ++++++++ src/main/antora/modules/ROOT/pages/index.adoc | 23 +- src/main/antora/modules/ROOT/pages/jpa.adoc | 4 +- .../{introduction.adoc => configuration.adoc} | 12 +- .../modules/ROOT/pages/{ => jpa}/faq.adoc | 0 .../ROOT/pages/{ => jpa}/glossary.adoc | 0 .../modules/ROOT/pages/jpa/misc-context.adoc | 2 +- .../modules/ROOT/pages/jpa/query-methods.adoc | 19 +- .../pages/{jpa => }/query-by-example.adoc | 2 +- .../pages/repositories/core-concepts.adoc | 1 + .../repositories/core-domain-events.adoc | 1 + .../pages/repositories/core-extensions.adoc | 1 + .../pages/repositories/create-instances.adoc | 1 + .../repositories/custom-implementations.adoc | 1 + .../ROOT/pages/repositories/definition.adoc | 1 + .../ROOT/pages/repositories/introduction.adoc | 7 + .../pages/repositories/null-handling.adoc | 1 + .../ROOT/pages/repositories/projections.adoc | 6 + .../query-keywords-reference.adoc | 1 + .../repositories/query-methods-details.adoc | 1 + .../query-return-types-reference.adoc | 1 + .../resources/antora-resources/antora.yml | 7 + 30 files changed, 304 insertions(+), 260 deletions(-) rename src/main/antora/modules/ROOT/pages/{jpa => }/auditing.adoc (93%) create mode 100644 src/main/antora/modules/ROOT/pages/commons/upgrade.adoc create mode 100644 src/main/antora/modules/ROOT/pages/envers/configuration.adoc create mode 100644 src/main/antora/modules/ROOT/pages/envers/introduction.adoc create mode 100644 src/main/antora/modules/ROOT/pages/envers/usage.adoc rename src/main/antora/modules/ROOT/pages/jpa/{introduction.adoc => configuration.adoc} (91%) rename src/main/antora/modules/ROOT/pages/{ => jpa}/faq.adoc (100%) rename src/main/antora/modules/ROOT/pages/{ => jpa}/glossary.adoc (100%) rename src/main/antora/modules/ROOT/pages/{jpa => }/query-by-example.adoc (92%) create mode 100644 src/main/antora/modules/ROOT/pages/repositories/core-concepts.adoc create mode 100644 src/main/antora/modules/ROOT/pages/repositories/core-domain-events.adoc create mode 100644 src/main/antora/modules/ROOT/pages/repositories/core-extensions.adoc create mode 100644 src/main/antora/modules/ROOT/pages/repositories/create-instances.adoc create mode 100644 src/main/antora/modules/ROOT/pages/repositories/custom-implementations.adoc create mode 100644 src/main/antora/modules/ROOT/pages/repositories/definition.adoc create mode 100644 src/main/antora/modules/ROOT/pages/repositories/introduction.adoc create mode 100644 src/main/antora/modules/ROOT/pages/repositories/null-handling.adoc create mode 100644 src/main/antora/modules/ROOT/pages/repositories/projections.adoc create mode 100644 src/main/antora/modules/ROOT/pages/repositories/query-keywords-reference.adoc create mode 100644 src/main/antora/modules/ROOT/pages/repositories/query-methods-details.adoc create mode 100644 src/main/antora/modules/ROOT/pages/repositories/query-return-types-reference.adoc diff --git a/spring-data-jpa-distribution/pom.xml b/spring-data-jpa-distribution/pom.xml index 453f49dea0..a458953182 100644 --- a/spring-data-jpa-distribution/pom.xml +++ b/spring-data-jpa-distribution/pom.xml @@ -37,6 +37,19 @@ maven-assembly-plugin + + org.apache.maven.plugins + maven-resources-plugin + + + + resources + + + + + + io.spring.maven.antora antora-maven-plugin @@ -44,17 +57,4 @@ - - - - antora - - - - - - - - - diff --git a/src/main/antora/antora-playbook.yml b/src/main/antora/antora-playbook.yml index 12ac5adfb4..d7c13a3d45 100644 --- a/src/main/antora/antora-playbook.yml +++ b/src/main/antora/antora-playbook.yml @@ -15,6 +15,11 @@ content: branches: HEAD start_path: src/main/antora worktrees: true + - url: https://github.com/spring-projects/spring-data-commons + # Refname matching: + # https://docs.antora.org/antora/latest/playbook/content-refname-matching/ + branches: [main, 3.2.x] + start_path: src/main/antora asciidoc: attributes: page-pagination: '' diff --git a/src/main/antora/modules/ROOT/nav.adoc b/src/main/antora/modules/ROOT/nav.adoc index 204efcda6f..1578f89bea 100644 --- a/src/main/antora/modules/ROOT/nav.adoc +++ b/src/main/antora/modules/ROOT/nav.adoc @@ -1,17 +1,34 @@ * xref:index.adoc[Overview] +** xref:commons/upgrade.adoc[] +* xref:repositories/introduction.adoc[] +** xref:repositories/core-concepts.adoc[] +** xref:repositories/definition.adoc[] +** xref:repositories/create-instances.adoc[] +** xref:repositories/query-methods-details.adoc[] +** xref:repositories/projections.adoc[] +** xref:repositories/custom-implementations.adoc[] +** xref:repositories/core-domain-events.adoc[] +** xref:repositories/core-extensions.adoc[] +** xref:repositories/null-handling.adoc[] +** xref:repositories/query-keywords-reference.adoc[] +** xref:repositories/query-return-types-reference.adoc[] * xref:jpa.adoc[] -** xref:jpa/introduction.adoc[] +** xref:jpa/configuration.adoc[] ** xref:jpa/entity-persistence.adoc[] ** xref:jpa/query-methods.adoc[] ** xref:jpa/stored-procedures.adoc[] ** xref:jpa/specifications.adoc[] -** xref:jpa/query-by-example.adoc[] +** xref:query-by-example.adoc[] ** xref:jpa/transactions.adoc[] ** xref:jpa/locking.adoc[] -** xref:jpa/auditing.adoc[] +** xref:auditing.adoc[] ** xref:jpa/misc-context.adoc[] ** xref:jpa/misc-merging-persistence-units.adoc[] ** xref:jpa/jpd-misc-cdi-integration.adoc[] +** xref:jpa/faq.adoc[] +** xref:jpa/glossary.adoc[] * xref:envers.adoc[] -* xref:faq.adoc[] -* xref:glossary.adoc[] +** xref:envers/introduction.adoc[] +** xref:envers/configuration.adoc[] +** xref:envers/usage.adoc[] +* https://github.com/spring-projects/spring-data-commons/wiki[Wiki] diff --git a/src/main/antora/modules/ROOT/pages/jpa/auditing.adoc b/src/main/antora/modules/ROOT/pages/auditing.adoc similarity index 93% rename from src/main/antora/modules/ROOT/pages/jpa/auditing.adoc rename to src/main/antora/modules/ROOT/pages/auditing.adoc index 20aeaa4c7c..62eb9ce584 100644 --- a/src/main/antora/modules/ROOT/pages/jpa/auditing.adoc +++ b/src/main/antora/modules/ROOT/pages/auditing.adoc @@ -1,8 +1,4 @@ -[[jpa.auditing]] -= JPA Auditing - -Spring Data JPA provides auditing based upon the foundation provided by {spring-data-commons-docs-url}/auditing.html[Spring Data Common's Auditing support]. - +include::{commons}@data-commons::page$auditing.adoc[] There is also a convenience base class, `AbstractAuditable`, which you can extend to avoid the need to manually implement the interface methods. Doing so increases the coupling of your domain classes to Spring Data, which might be something you want to avoid. Usually, the annotation-based way of defining auditing metadata is preferred as it is less invasive and more flexible. diff --git a/src/main/antora/modules/ROOT/pages/commons/upgrade.adoc b/src/main/antora/modules/ROOT/pages/commons/upgrade.adoc new file mode 100644 index 0000000000..51a9189aa0 --- /dev/null +++ b/src/main/antora/modules/ROOT/pages/commons/upgrade.adoc @@ -0,0 +1 @@ +include::{commons}@data-commons::page$upgrade.adoc[] diff --git a/src/main/antora/modules/ROOT/pages/envers.adoc b/src/main/antora/modules/ROOT/pages/envers.adoc index df8589135a..2e56e5e1b9 100644 --- a/src/main/antora/modules/ROOT/pages/envers.adoc +++ b/src/main/antora/modules/ROOT/pages/envers.adoc @@ -1,204 +1,5 @@ [[envers]] -= Spring Data Envers += Envers +:page-section-summary-toc: 1 -[[envers.what.is.spring.data]] -== What is Spring Data Envers? - -Spring Data Envers makes typical Envers queries available in repositories for Spring Data JPA. -It differs from other Spring Data modules in that it is always used in combination with another Spring Data Module: Spring Data JPA. - -[[envers.what]] -== What is Envers? - -Envers is a https://hibernate.org/orm/envers/[Hibernate module] that adds auditing capabilities to JPA entities. -This documentation assumes you are familiar with Envers, just as Spring Data Envers relies on Envers being properly configured. - -[[envers.configuration]] -== Configuration - -As a starting point for using Spring Data Envers, you need a project with Spring Data JPA on the classpath and an additional `spring-data-envers` dependency: - -==== -[source,xml,subs="+attributes"] ----- - - - - - - org.springframework.data - spring-data-envers - {version} - - - ----- -==== - -This also brings `hibernate-envers` into the project as a transient dependency. - -To enable Spring Data Envers and Spring Data JPA, we need to configure two beans and a special `repositoryFactoryBeanClass`: - -==== -[source,java] ----- -@Configuration -@EnableEnversRepositories -@EnableTransactionManagement -public class EnversDemoConfiguration { - - @Bean - public DataSource dataSource() { - - EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder(); - return builder.setType(EmbeddedDatabaseType.HSQL).build(); - } - - @Bean - public LocalContainerEntityManagerFactoryBean entityManagerFactory() { - - HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); - vendorAdapter.setGenerateDdl(true); - - LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean(); - factory.setJpaVendorAdapter(vendorAdapter); - factory.setPackagesToScan("example.springdata.jpa.envers"); - factory.setDataSource(dataSource()); - return factory; - } - - @Bean - public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) { - - JpaTransactionManager txManager = new JpaTransactionManager(); - txManager.setEntityManagerFactory(entityManagerFactory); - return txManager; - } -} ----- -==== - -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: - -==== -[source,java] ----- -interface PersonRepository - extends CrudRepository, - RevisionRepository // <1> -{} ----- -<1> The first type parameter (`Person`) denotes the entity type, the second (`Long`) denotes the type of the id property, and the last one (`Long`) is the type of the revision number. -For Envers in default configuration, the revision number parameter should be `Integer` or `Long`. -==== - -The entity for that repository must be an entity with Envers auditing enabled (that is, it must have an `@Audited` annotation): - -==== -[source,java] ----- -@Entity -@Audited -class Person { - - @Id @GeneratedValue - Long id; - String name; - @Version Long version; -} ----- -==== - -[[envers.usage]] -== Usage - -You can now use the methods from `RevisionRepository` to query the revisions of the entity, as the following test case shows: - -==== -[source,java] ----- -@ExtendWith(SpringExtension.class) -@Import(EnversDemoConfiguration.class) // <1> -class EnversIntegrationTests { - - final PersonRepository repository; - final TransactionTemplate tx; - - EnversIntegrationTests(@Autowired PersonRepository repository, @Autowired PlatformTransactionManager tm) { - this.repository = repository; - this.tx = new TransactionTemplate(tm); - } - - @Test - void testRepository() { - - Person updated = preparePersonHistory(); - - Revisions revisions = repository.findRevisions(updated.id); - - Iterator> revisionIterator = revisions.iterator(); - - checkNextRevision(revisionIterator, "John", RevisionType.INSERT); - checkNextRevision(revisionIterator, "Jonny", RevisionType.UPDATE); - checkNextRevision(revisionIterator, null, RevisionType.DELETE); - assertThat(revisionIterator.hasNext()).isFalse(); - - } - - /** - * Checks that the next element in the iterator is a Revision entry referencing a Person - * with the given name after whatever change brought that Revision into existence. - *

- * As a side effect the Iterator gets advanced by one element. - * - * @param revisionIterator the iterator to be tested. - * @param name the expected name of the Person referenced by the Revision. - * @param revisionType the type of the revision denoting if it represents an insert, update or delete. - */ - private void checkNextRevision(Iterator> revisionIterator, String name, - RevisionType revisionType) { - - assertThat(revisionIterator.hasNext()).isTrue(); - Revision revision = revisionIterator.next(); - assertThat(revision.getEntity().name).isEqualTo(name); - assertThat(revision.getMetadata().getRevisionType()).isEqualTo(revisionType); - } - - /** - * Creates a Person with a couple of changes so it has a non-trivial revision history. - * @return the created Person. - */ - private Person preparePersonHistory() { - - Person john = new Person(); - john.setName("John"); - - // create - Person saved = tx.execute(__ -> repository.save(john)); - assertThat(saved).isNotNull(); - - saved.setName("Jonny"); - - // update - Person updated = tx.execute(__ -> repository.save(saved)); - assertThat(updated).isNotNull(); - - // delete - tx.executeWithoutResult(__ -> repository.delete(updated)); - return updated; - } -} ----- -<1> This references the application context configuration presented earlier (in the xref:envers.adoc#envers.configuration[Configuration] section). -==== - -[[envers.resources]] -== Further Resources - -You can download the https://github.com/spring-projects/spring-data-examples[Spring Data Envers example in the Spring Data Examples repository] and play around with to get a feel for how the library works. - -You should also check out the {spring-data-commons-javadoc-base}/org/springframework/data/repository/history/RevisionRepository.html[Javadoc for `RevisionRepository`] and related classes. - -You can ask questions at https://stackoverflow.com/questions/tagged/spring-data-envers[Stackoverflow by using the `spring-data-envers` tag]. - -The https://github.com/spring-projects/spring-data-jpa[source code and issue tracker for Spring Data Envers is hosted at GitHub] (as a module of Spring Data JPA). +This chapter points out the specialties for repository support for Envers. This builds on the core repository support explained earlier. Make sure you have a sound understanding of the basic concepts explained there. diff --git a/src/main/antora/modules/ROOT/pages/envers/configuration.adoc b/src/main/antora/modules/ROOT/pages/envers/configuration.adoc new file mode 100644 index 0000000000..c144deb915 --- /dev/null +++ b/src/main/antora/modules/ROOT/pages/envers/configuration.adoc @@ -0,0 +1,95 @@ +[[envers.configuration]] += Configuration + +As a starting point for using Spring Data Envers, you need a project with Spring Data JPA on the classpath and an additional `spring-data-envers` dependency: + +==== +[source,xml,subs="+attributes"] +---- + + + + + + org.springframework.data + spring-data-envers + {version} + + + +---- +==== + +This also brings `hibernate-envers` into the project as a transient dependency. + +To enable Spring Data Envers and Spring Data JPA, we need to configure two beans and a special `repositoryFactoryBeanClass`: + +==== +[source,java] +---- +@Configuration +@EnableEnversRepositories +@EnableTransactionManagement +public class EnversDemoConfiguration { + + @Bean + public DataSource dataSource() { + + EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder(); + return builder.setType(EmbeddedDatabaseType.HSQL).build(); + } + + @Bean + public LocalContainerEntityManagerFactoryBean entityManagerFactory() { + + HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); + vendorAdapter.setGenerateDdl(true); + + LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean(); + factory.setJpaVendorAdapter(vendorAdapter); + factory.setPackagesToScan("example.springdata.jpa.envers"); + factory.setDataSource(dataSource()); + return factory; + } + + @Bean + public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) { + + JpaTransactionManager txManager = new JpaTransactionManager(); + txManager.setEntityManagerFactory(entityManagerFactory); + return txManager; + } +} +---- +==== + +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: + +==== +[source,java] +---- +interface PersonRepository + extends CrudRepository, + RevisionRepository // <1> +{} +---- +<1> The first type parameter (`Person`) denotes the entity type, the second (`Long`) denotes the type of the id property, and the last one (`Long`) is the type of the revision number. +For Envers in default configuration, the revision number parameter should be `Integer` or `Long`. +==== + +The entity for that repository must be an entity with Envers auditing enabled (that is, it must have an `@Audited` annotation): + +==== +[source,java] +---- +@Entity +@Audited +class Person { + + @Id @GeneratedValue + Long id; + String name; + @Version Long version; +} +---- +==== diff --git a/src/main/antora/modules/ROOT/pages/envers/introduction.adoc b/src/main/antora/modules/ROOT/pages/envers/introduction.adoc new file mode 100644 index 0000000000..c082c3cf56 --- /dev/null +++ b/src/main/antora/modules/ROOT/pages/envers/introduction.adoc @@ -0,0 +1,14 @@ +[[envers.introduction]] += Introduction + +[[envers.what.is.spring.data]] +== What is Spring Data Envers? + +Spring Data Envers makes typical Envers queries available in repositories for Spring Data JPA. +It differs from other Spring Data modules in that it is always used in combination with another Spring Data Module: Spring Data JPA. + +[[envers.what]] +== What is Envers? + +Envers is a https://hibernate.org/orm/envers/[Hibernate module] that adds auditing capabilities to JPA entities. +This documentation assumes you are familiar with Envers, just as Spring Data Envers relies on Envers being properly configured. diff --git a/src/main/antora/modules/ROOT/pages/envers/usage.adoc b/src/main/antora/modules/ROOT/pages/envers/usage.adoc new file mode 100644 index 0000000000..96ee5ba3d3 --- /dev/null +++ b/src/main/antora/modules/ROOT/pages/envers/usage.adoc @@ -0,0 +1,93 @@ +[[envers.usage]] += Usage + +You can now use the methods from `RevisionRepository` to query the revisions of the entity, as the following test case shows: + +==== +[source,java] +---- +@ExtendWith(SpringExtension.class) +@Import(EnversDemoConfiguration.class) // <1> +class EnversIntegrationTests { + + final PersonRepository repository; + final TransactionTemplate tx; + + EnversIntegrationTests(@Autowired PersonRepository repository, @Autowired PlatformTransactionManager tm) { + this.repository = repository; + this.tx = new TransactionTemplate(tm); + } + + @Test + void testRepository() { + + Person updated = preparePersonHistory(); + + Revisions revisions = repository.findRevisions(updated.id); + + Iterator> revisionIterator = revisions.iterator(); + + checkNextRevision(revisionIterator, "John", RevisionType.INSERT); + checkNextRevision(revisionIterator, "Jonny", RevisionType.UPDATE); + checkNextRevision(revisionIterator, null, RevisionType.DELETE); + assertThat(revisionIterator.hasNext()).isFalse(); + + } + + /** + * Checks that the next element in the iterator is a Revision entry referencing a Person + * with the given name after whatever change brought that Revision into existence. + *

+ * As a side effect the Iterator gets advanced by one element. + * + * @param revisionIterator the iterator to be tested. + * @param name the expected name of the Person referenced by the Revision. + * @param revisionType the type of the revision denoting if it represents an insert, update or delete. + */ + private void checkNextRevision(Iterator> revisionIterator, String name, + RevisionType revisionType) { + + assertThat(revisionIterator.hasNext()).isTrue(); + Revision revision = revisionIterator.next(); + assertThat(revision.getEntity().name).isEqualTo(name); + assertThat(revision.getMetadata().getRevisionType()).isEqualTo(revisionType); + } + + /** + * Creates a Person with a couple of changes so it has a non-trivial revision history. + * @return the created Person. + */ + private Person preparePersonHistory() { + + Person john = new Person(); + john.setName("John"); + + // create + Person saved = tx.execute(__ -> repository.save(john)); + assertThat(saved).isNotNull(); + + saved.setName("Jonny"); + + // update + Person updated = tx.execute(__ -> repository.save(saved)); + assertThat(updated).isNotNull(); + + // delete + tx.executeWithoutResult(__ -> repository.delete(updated)); + return updated; + } +} +---- +<1> This references the application context configuration presented earlier (in the xref:envers.adoc#envers.configuration[Configuration] section). +==== + +[[envers.resources]] +== Further Resources + +You can download the https://github.com/spring-projects/spring-data-examples[Spring Data Envers example in the Spring Data Examples repository] and play around with to get a feel for how the library works. + +You should also check out the {spring-data-commons-javadoc-base}/org/springframework/data/repository/history/RevisionRepository.html[Javadoc for `RevisionRepository`] and related classes. + +You can ask questions at https://stackoverflow.com/questions/tagged/spring-data-envers[Stackoverflow by using the `spring-data-envers` tag]. + +The https://github.com/spring-projects/spring-data-jpa[source code and issue tracker for Spring Data Envers is hosted at GitHub] (as a module of Spring Data JPA). diff --git a/src/main/antora/modules/ROOT/pages/index.adoc b/src/main/antora/modules/ROOT/pages/index.adoc index 064d46877f..f6c6e67922 100644 --- a/src/main/antora/modules/ROOT/pages/index.adoc +++ b/src/main/antora/modules/ROOT/pages/index.adoc @@ -1,24 +1,21 @@ [[spring-data-jpa-reference-documentation]] = Spring Data JPA -Oliver Gierke; Thomas Darimont; Christoph Strobl; Mark Paluch; Jay Bryant; Greg Turnquist :revnumber: {version} :revdate: {localdate} :feature-scroll: true -(C) 2008-2023 The original authors. +_Spring Data JPA provides repository support for the Jakarta Persistence API (JPA). +It eases development of applications with a consistent programming model that need to access JPA data sources._ -NOTE: Copies of this document may be made for your own use and for distribution to others, provided that you do not charge any fee for such copies and further provided that each copy contains this Copyright Notice, whether distributed in print or electronically. +[horizontal] +xref:jpa.adoc[JPA] :: JPA and JPA Repositories +xref:envers.adoc[Envers] :: Support for Envers Revision Repositories +https://github.com/spring-projects/spring-data-commons/wiki[Wiki] :: What's New, +Upgrade Notes, Supported Versions, additional cross-version information. -[[preface]] -== Preface -:page-section-summary-toc: 1 +Oliver Gierke, Thomas Darimont, Christoph Strobl, Mark Paluch, Jay Bryant, Greg Turnquist -Spring Data JPA provides repository support for the Jakarta Persistence API (JPA). It eases development of applications that need to access JPA data sources. +(C) 2008-2023 VMware, Inc. -[[project]] -== Project Metadata +Copies of this document may be made for your own use and for distribution to others, provided that you do not charge any fee for such copies and further provided that each copy contains this Copyright Notice, whether distributed in print or electronically. -* Version control: https://github.com/spring-projects/spring-data-jpa -* Bugtracker: https://github.com/spring-projects/spring-data-jpa/issues -* Milestone repository: https://repo.spring.io/milestone -* Snapshot repository: https://repo.spring.io/snapshot \ No newline at end of file diff --git a/src/main/antora/modules/ROOT/pages/jpa.adoc b/src/main/antora/modules/ROOT/pages/jpa.adoc index eae798bbc7..b490dfcaa6 100644 --- a/src/main/antora/modules/ROOT/pages/jpa.adoc +++ b/src/main/antora/modules/ROOT/pages/jpa.adoc @@ -1,6 +1,6 @@ [[jpa.repositories]] -= JPA Repositories += JPA :page-section-summary-toc: 1 -This chapter points out the specialties for repository support for JPA. This builds on the core repository support explained in {spring-data-commons-docs-url}/repositories.html[Working with Spring Data Repositories]. Make sure you have a sound understanding of the basic concepts explained there. +This chapter points out the specialties for repository support for JPA. This builds on the core repository support explained in xref:repositories/introduction.adoc[Working with Spring Data Repositories]. Make sure you have a sound understanding of the basic concepts explained there. diff --git a/src/main/antora/modules/ROOT/pages/jpa/introduction.adoc b/src/main/antora/modules/ROOT/pages/jpa/configuration.adoc similarity index 91% rename from src/main/antora/modules/ROOT/pages/jpa/introduction.adoc rename to src/main/antora/modules/ROOT/pages/jpa/configuration.adoc index d1f66fd30a..5307e4e986 100644 --- a/src/main/antora/modules/ROOT/pages/jpa/introduction.adoc +++ b/src/main/antora/modules/ROOT/pages/jpa/configuration.adoc @@ -1,10 +1,10 @@ -[[jpa.introduction]] -= Introduction +[[jpa.configuration]] += Configuration -This section describes the basics of configuring Spring Data JPA through either: +This section describes configuring Spring Data JPA through either: -* "`xref:jpa/introduction.adoc#jpa.namespace[Spring Namespace]`" (XML configuration) -* "`xref:jpa/introduction.adoc#jpa.java-config[Annotation-based Configuration]`" (Java configuration) +* "`<>`" (XML configuration) +* "`<>`" (Java configuration) [[jpa.java-config]] == Annotation-based Configuration @@ -79,7 +79,7 @@ The JPA module of Spring Data contains a custom namespace that allows defining r TIP: Which is better, JavaConfig or XML? XML is how Spring was configured long ago. In today's era of fast-growing Java, record types, annotations, and more, new projects typically use as much pure Java as possible. While there is no immediate plan to remove XML support, some of the newest features MAY not be available through XML. -Using the `repositories` element looks up Spring Data repositories as described in {spring-data-commons-docs-url}/repositories/create-instances.html[Creating Repository Instances]. Beyond that, it activates persistence exception translation for all beans annotated with `@Repository`, to let exceptions being thrown by the JPA persistence providers be converted into Spring's `DataAccessException` hierarchy. +Using the `repositories` element looks up Spring Data repositories as described in xref:repositories/create-instances.adoc[Creating Repository Instances]. Beyond that, it activates persistence exception translation for all beans annotated with `@Repository`, to let exceptions being thrown by the JPA persistence providers be converted into Spring's `DataAccessException` hierarchy. [[jpa.namespace.custom-namespace-attributes]] === Custom Namespace Attributes diff --git a/src/main/antora/modules/ROOT/pages/faq.adoc b/src/main/antora/modules/ROOT/pages/jpa/faq.adoc similarity index 100% rename from src/main/antora/modules/ROOT/pages/faq.adoc rename to src/main/antora/modules/ROOT/pages/jpa/faq.adoc diff --git a/src/main/antora/modules/ROOT/pages/glossary.adoc b/src/main/antora/modules/ROOT/pages/jpa/glossary.adoc similarity index 100% rename from src/main/antora/modules/ROOT/pages/glossary.adoc rename to src/main/antora/modules/ROOT/pages/jpa/glossary.adoc diff --git a/src/main/antora/modules/ROOT/pages/jpa/misc-context.adoc b/src/main/antora/modules/ROOT/pages/jpa/misc-context.adoc index 7cdb5feff4..a12840ad44 100644 --- a/src/main/antora/modules/ROOT/pages/jpa/misc-context.adoc +++ b/src/main/antora/modules/ROOT/pages/jpa/misc-context.adoc @@ -1,7 +1,7 @@ [[jpa.misc.jpa-context]] = Using `JpaContext` in Custom Implementations -When working with multiple `EntityManager` instances and <>, you need to wire the correct `EntityManager` into the repository implementation class. You can do so by explicitly naming the `EntityManager` in the `@PersistenceContext` annotation or, if the `EntityManager` is `@Autowired`, by using `@Qualifier`. +When working with multiple `EntityManager` instances and xref:repositories/custom-implementations.adoc#repositories.custom-implementations[custom repository implementations], you need to wire the correct `EntityManager` into the repository implementation class. You can do so by explicitly naming the `EntityManager` in the `@PersistenceContext` annotation or, if the `EntityManager` is `@Autowired`, by using `@Qualifier`. As of Spring Data JPA 1.9, Spring Data JPA includes a class called `JpaContext` that lets you obtain the `EntityManager` by managed domain class, assuming it is managed by only one of the `EntityManager` instances in the application. The following example shows how to use `JpaContext` in a custom repository: diff --git a/src/main/antora/modules/ROOT/pages/jpa/query-methods.adoc b/src/main/antora/modules/ROOT/pages/jpa/query-methods.adoc index 39be17e2d1..1b59f44ad3 100644 --- a/src/main/antora/modules/ROOT/pages/jpa/query-methods.adoc +++ b/src/main/antora/modules/ROOT/pages/jpa/query-methods.adoc @@ -31,7 +31,7 @@ public interface UserRepository extends Repository { List findByEmailAddressAndLastname(String emailAddress, String lastname); } ---- -We create a query using the JPA criteria API from this, but, essentially, this translates into the following query: `select u from User u where u.emailAddress = ?1 and u.lastname = ?2`. Spring Data JPA does a property check and traverses nested properties, as described in {spring-data-commons-docs-url}/repositories/query-methods-details.html#repositories.query-methods.query-property-expressions[Property Expressions]. +We create a query using the JPA criteria API from this, but, essentially, this translates into the following query: `select u from User u where u.emailAddress = ?1 and u.lastname = ?2`. Spring Data JPA does a property check and traverses nested properties, as described in xref:repositories/query-methods-details.adoc#repositories.query-methods.query-property-expressions[Property Expressions]. ==== The following table describes the keywords supported for JPA and what a method containing that keyword translates to: @@ -67,7 +67,7 @@ The following table describes the keywords supported for JPA and what a method c |`IgnoreCase`|`findByFirstnameIgnoreCase`|`… where UPPER(x.firstname) = UPPER(?1)` |=============== -NOTE: `In` and `NotIn` also take any subclass of `Collection` as a parameter as well as arrays or varargs. For other syntactical versions of the same logical operator, check {spring-data-commons-docs-url}/repository-query-keywords-reference.html[Repository query keywords]. +NOTE: `In` and `NotIn` also take any subclass of `Collection` as a parameter as well as arrays or varargs. For other syntactical versions of the same logical operator, check xref:repositories/query-keywords-reference.adoc[Repository query keywords]. [WARNING] ==== @@ -350,16 +350,16 @@ When working with large data sets, <> can help You have multiple options to consume large query results: -1. <>. +1. xref:repositories/query-methods-details.adoc#repositories.paging-and-sorting[Paging]. You have learned in the previous chapter about `Pageable` and `PageRequest`. 2. <>. This is a lighter variant than paging because it does not require the total result count. 3. <>. This method avoids https://use-the-index-luke.com/no-offset[the shortcomings of offset-based result retrieval by leveraging database indexes]. -Read more on <> for your particular arrangement. +Read more on xref:repositories/query-methods-details.adoc#repositories.scrolling.guidance,which method to use best>> for your particular arrangement. -You can use the Scroll API with query methods, xref:jpa/query-by-example.adoc[Query-by-Example], and <>. +You can use the Scroll API with query methods, xref:query-by-example.adoc[Query-by-Example], and xref:repositories/core-extensions.adoc#core.extensions.querydsl[Querydsl]. NOTE: Scrolling with String-based query methods is not yet supported. Scrolling is also not supported using stored `@Procedure` query methods. @@ -507,7 +507,7 @@ But sometimes, your query may simply be too complicated for the techniques offer In that situation, consider: * If you haven't already, simply write the query yourself using xref:jpa/query-methods.adoc#jpa.query-methods.at-query[`@Query`]. -* If that doesn't fit your needs, consider implementing a <>. This lets you register a method in your repository while leaving the implementation completely up to you. This gives you the ability to: +* If that doesn't fit your needs, consider implementing a xref:repositories/custom-implementations.adoc#repositories.custom-implementations[custom implementation]. This lets you register a method in your repository while leaving the implementation completely up to you. This gives you the ability to: ** Talk directly to the `EntityManager` (writing pure HQL/JPQL/EQL/native SQL or using the *Criteria API*) ** Leverage Spring Framework's `JdbcTemplate` (native SQL) ** Use another 3rd-party database toolkit. @@ -773,9 +773,4 @@ public interface GroupRepository extends CrudRepository { ---- ==== -[[projections]] -== Projections - -Spring Data JPA supports {spring-data-commons-docs-url}/repository-projections.html[Spring Data Commons Projections]. - -NOTE: It is important to note that {spring-data-commons-docs-url}/repository-projections.html#projections.dtos[Class-based projections] with JPQL is limited to *constructor expressions* in your JPQL expression, e.g. `SELECT new com.example.NamesOnly(u.firstname, u.lastname) from User u`. (Note the usage of a FQDN for the DTO type!) This JPQL expression can be used in `@Query` annotations as well where you define any named queries. And it's important to point out that class-based projections do not work with native queries AT ALL. As a workaround you may use named queries with `ResultSetMapping` or the Hibernate specific https://docs.jboss.org/hibernate/orm/6.0/javadocs/org/hibernate/transform/ResultTransformer.html[`ResultTransformer`] \ No newline at end of file +include::{commons}@data-commons::page$repositories/scrolling.adoc[leveloffset=+1] diff --git a/src/main/antora/modules/ROOT/pages/jpa/query-by-example.adoc b/src/main/antora/modules/ROOT/pages/query-by-example.adoc similarity index 92% rename from src/main/antora/modules/ROOT/pages/jpa/query-by-example.adoc rename to src/main/antora/modules/ROOT/pages/query-by-example.adoc index 2a7c661db4..5f427c29ba 100644 --- a/src/main/antora/modules/ROOT/pages/jpa/query-by-example.adoc +++ b/src/main/antora/modules/ROOT/pages/query-by-example.adoc @@ -1,6 +1,6 @@ = Query by Example -Spring Data JPA leverages {spring-data-commons-docs-url}/query-by-example.html[Spring Data Commons support for Query by Example]. +include::{commons}@data-commons::page$query-by-example.adoc[leveloffset=+1] [[query-by-example.running]] In Spring Data JPA, you can use Query by Example with Repositories, as shown in the following example: diff --git a/src/main/antora/modules/ROOT/pages/repositories/core-concepts.adoc b/src/main/antora/modules/ROOT/pages/repositories/core-concepts.adoc new file mode 100644 index 0000000000..4ae3ce6763 --- /dev/null +++ b/src/main/antora/modules/ROOT/pages/repositories/core-concepts.adoc @@ -0,0 +1 @@ +include::{commons}@data-commons::page$repositories/core-concepts.adoc[] diff --git a/src/main/antora/modules/ROOT/pages/repositories/core-domain-events.adoc b/src/main/antora/modules/ROOT/pages/repositories/core-domain-events.adoc new file mode 100644 index 0000000000..f84313e9da --- /dev/null +++ b/src/main/antora/modules/ROOT/pages/repositories/core-domain-events.adoc @@ -0,0 +1 @@ +include::{commons}@data-commons::page$repositories/core-domain-events.adoc[] diff --git a/src/main/antora/modules/ROOT/pages/repositories/core-extensions.adoc b/src/main/antora/modules/ROOT/pages/repositories/core-extensions.adoc new file mode 100644 index 0000000000..a7c2ff8d3c --- /dev/null +++ b/src/main/antora/modules/ROOT/pages/repositories/core-extensions.adoc @@ -0,0 +1 @@ +include::{commons}@data-commons::page$repositories/core-extensions.adoc[] diff --git a/src/main/antora/modules/ROOT/pages/repositories/create-instances.adoc b/src/main/antora/modules/ROOT/pages/repositories/create-instances.adoc new file mode 100644 index 0000000000..2ae01801b1 --- /dev/null +++ b/src/main/antora/modules/ROOT/pages/repositories/create-instances.adoc @@ -0,0 +1 @@ +include::{commons}@data-commons::page$repositories/create-instances.adoc[] diff --git a/src/main/antora/modules/ROOT/pages/repositories/custom-implementations.adoc b/src/main/antora/modules/ROOT/pages/repositories/custom-implementations.adoc new file mode 100644 index 0000000000..c7615191a6 --- /dev/null +++ b/src/main/antora/modules/ROOT/pages/repositories/custom-implementations.adoc @@ -0,0 +1 @@ +include::{commons}@data-commons::page$repositories/custom-implementations.adoc[] diff --git a/src/main/antora/modules/ROOT/pages/repositories/definition.adoc b/src/main/antora/modules/ROOT/pages/repositories/definition.adoc new file mode 100644 index 0000000000..bd65a8af83 --- /dev/null +++ b/src/main/antora/modules/ROOT/pages/repositories/definition.adoc @@ -0,0 +1 @@ +include::{commons}@data-commons::page$repositories/definition.adoc[] diff --git a/src/main/antora/modules/ROOT/pages/repositories/introduction.adoc b/src/main/antora/modules/ROOT/pages/repositories/introduction.adoc new file mode 100644 index 0000000000..2eda81a93c --- /dev/null +++ b/src/main/antora/modules/ROOT/pages/repositories/introduction.adoc @@ -0,0 +1,7 @@ +[[common.basics]] += Introduction +:page-section-summary-toc: 1 + +This chapter explains the basic foundations of Spring Data repositories. Before continuing to the JPA specifics, make sure you have a sound understanding of the basic concepts explained here. + +The goal of the Spring Data repository abstraction is to significantly reduce the amount of boilerplate code required to implement data access layers for various persistence stores. diff --git a/src/main/antora/modules/ROOT/pages/repositories/null-handling.adoc b/src/main/antora/modules/ROOT/pages/repositories/null-handling.adoc new file mode 100644 index 0000000000..081bac9f61 --- /dev/null +++ b/src/main/antora/modules/ROOT/pages/repositories/null-handling.adoc @@ -0,0 +1 @@ +include::{commons}@data-commons::page$repositories/null-handling.adoc[] diff --git a/src/main/antora/modules/ROOT/pages/repositories/projections.adoc b/src/main/antora/modules/ROOT/pages/repositories/projections.adoc new file mode 100644 index 0000000000..5635695699 --- /dev/null +++ b/src/main/antora/modules/ROOT/pages/repositories/projections.adoc @@ -0,0 +1,6 @@ +[[jpa.projections]] += Projections + +include::{commons}@data-commons::page$repositories/projections.adoc[leveloffset=+1] + +NOTE: It is important to note that <> with JPQL is limited to *constructor expressions* in your JPQL expression, e.g. `SELECT new com.example.NamesOnly(u.firstname, u.lastname) from User u`. (Note the usage of a FQDN for the DTO type!) This JPQL expression can be used in `@Query` annotations as well where you define any named queries. And it's important to point out that class-based projections do not work with native queries AT ALL. As a workaround you may use named queries with `ResultSetMapping` or the Hibernate specific https://docs.jboss.org/hibernate/orm/6.0/javadocs/org/hibernate/transform/ResultTransformer.html[`ResultTransformer`] diff --git a/src/main/antora/modules/ROOT/pages/repositories/query-keywords-reference.adoc b/src/main/antora/modules/ROOT/pages/repositories/query-keywords-reference.adoc new file mode 100644 index 0000000000..e495eddc6b --- /dev/null +++ b/src/main/antora/modules/ROOT/pages/repositories/query-keywords-reference.adoc @@ -0,0 +1 @@ +include::{commons}@data-commons::page$repositories/query-keywords-reference.adoc[] diff --git a/src/main/antora/modules/ROOT/pages/repositories/query-methods-details.adoc b/src/main/antora/modules/ROOT/pages/repositories/query-methods-details.adoc new file mode 100644 index 0000000000..dfe4814955 --- /dev/null +++ b/src/main/antora/modules/ROOT/pages/repositories/query-methods-details.adoc @@ -0,0 +1 @@ +include::{commons}@data-commons::page$repositories/query-methods-details.adoc[] diff --git a/src/main/antora/modules/ROOT/pages/repositories/query-return-types-reference.adoc b/src/main/antora/modules/ROOT/pages/repositories/query-return-types-reference.adoc new file mode 100644 index 0000000000..a73c3201d0 --- /dev/null +++ b/src/main/antora/modules/ROOT/pages/repositories/query-return-types-reference.adoc @@ -0,0 +1 @@ +include::{commons}@data-commons::page$repositories/query-return-types-reference.adoc[] diff --git a/src/main/antora/resources/antora-resources/antora.yml b/src/main/antora/resources/antora-resources/antora.yml index f42c5ef7af..61386b7d27 100644 --- a/src/main/antora/resources/antora-resources/antora.yml +++ b/src/main/antora/resources/antora-resources/antora.yml @@ -7,7 +7,14 @@ asciidoc: springversionshort: ${spring.short} springversion: ${spring} attribute-missing: 'warn' + commons: ${springdata.commons.docs} + include-xml-namespaces: false spring-data-commons-docs-url: https://docs.spring.io/spring-data-commons/reference spring-data-commons-javadoc-base: https://docs.spring.io/spring-data/commons/docs/${springdata.commons}/api/ springdocsurl: https://docs.spring.io/spring-framework/reference/{springversionshort} springjavadocurl: https://docs.spring.io/spring-framework/docs/${spring}/javadoc-api + spring-framework-docs: '{springdocsurl}' + spring-framework-javadoc: '{springjavadocurl}' + springhateoasversion: ${spring-hateoas} + releasetrainversion: ${releasetrain} + store: Jpa