Skip to content

Commit 9ba2803

Browse files
authored
documentation for Hibernate Data Repositories (#8178)
documentation for Hibernate Data Repositories Signed-off-by: Gavin King <gavin@hibernate.org>
1 parent 1c71bb6 commit 9ba2803

File tree

6 files changed

+1076
-0
lines changed

6 files changed

+1076
-0
lines changed

documentation/documentation.gradle

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,54 @@ def renderQueryLanguageGuidePdfTask = tasks.register( 'renderQueryLanguageGuideP
456456
attributes jpaJavadocUrlPrefix: "https://javaee.github.io/javaee-spec/javadocs/javax/persistence/"
457457
}
458458

459+
def renderRepositoriesHtmlTask = tasks.register( 'renderRepositoriesHtml', AsciidoctorTask ) { task ->
460+
task.group = "Documentation"
461+
task.description = 'Renders the Hibernate Data Repositories document in HTML format using Asciidoctor.'
462+
463+
task.inputs.property "hibernate-version", project.ormVersion
464+
465+
task.sourceDir = file( 'src/main/asciidoc/repositories' )
466+
task.sources 'Hibernate_Data_Repositories.adoc'
467+
468+
task.outputDir = layout.buildDirectory.dir( "asciidoc/repositories/html_single" )
469+
470+
task.attributes linkcss: true,
471+
stylesheet: "css/hibernate.css",
472+
docinfo: 'private',
473+
jpaJavadocUrlPrefix: "https://javaee.github.io/javaee-spec/javadocs/javax/persistence/"
474+
475+
task.resources {
476+
from( 'src/main/asciidoc/repositories/' ) {
477+
include 'images/**'
478+
}
479+
from( 'src/main/style/asciidoctor' ) {
480+
include 'images/**'
481+
}
482+
from( 'src/main/style/asciidoctor' ) {
483+
include 'css/**'
484+
}
485+
from( 'src/main/style/asciidoctor' ) {
486+
include 'js/**'
487+
}
488+
}
489+
}
490+
491+
def renderRepositoriesPdfTask = tasks.register( 'renderRepositoriesPdf', AsciidoctorPdfTask ) { task ->
492+
group = "Documentation"
493+
description = 'Renders the Hibernate Data Repositories document in PDF format using Asciidoctor.'
494+
495+
inputs.property "hibernate-version", project.ormVersion
496+
497+
sourceDir = file( 'src/main/asciidoc/repositories' )
498+
baseDir = file( 'src/main/asciidoc/repositories' )
499+
sources {
500+
include 'Hibernate_Data_Repositories.adoc'
501+
}
502+
outputDir = layout.buildDirectory.dir( "asciidoc/repositories/pdf" )
503+
504+
attributes jpaJavadocUrlPrefix: "https://javaee.github.io/javaee-spec/javadocs/javax/persistence/"
505+
}
506+
459507
//noinspection GroovyUnusedAssignment
460508
def renderQueryLanguageGuidesTask = tasks.register( 'renderQueryLanguageGuides' ) { task ->
461509
group = "Documentation"
@@ -466,6 +514,17 @@ def renderQueryLanguageGuidesTask = tasks.register( 'renderQueryLanguageGuides'
466514
tasks.buildDocs.dependsOn task
467515
}
468516

517+
//noinspection GroovyUnusedAssignment
518+
def renderRepositoriesTask = tasks.register( 'renderRepositories' ) { task ->
519+
group = "Documentation"
520+
description = 'Renders Hibernate Data Repositories documentation in all formats.'
521+
task.dependsOn renderRepositoriesHtmlTask
522+
task.dependsOn renderRepositoriesPdfTask
523+
524+
tasks.buildDocs.dependsOn task
525+
}
526+
527+
469528

470529
// User Guide ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
471530

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
[[configuration-integration]]
2+
== Configuration and integration
3+
4+
Getting started with Hibernate Data Repositories involves the following steps:
5+
6+
1. set up a project with Hibernate ORM and `HibernateProcessor`,
7+
2. configure a persistence unit,
8+
3. make sure a `StatelessSession` for that persistence unit is available for injection, and then
9+
4. inject a repository using CDI or some other implementation of `jakarta.inject`.
10+
11+
=== Project setup
12+
13+
We definitely need the following dependencies in our project:
14+
15+
.Required dependencies
16+
|===
17+
| Dependency | Explanation
18+
19+
| `jakarta.data:jakarta.data-api` | The Jakarta Data API
20+
| `org.hibernate.orm:hibernate-core` | Hibernate ORM
21+
| `org.hibernate.orm:hibernate-jpamodelgen` | The annotation processor itself
22+
|===
23+
24+
And we'll need to pick a JDBC driver:
25+
26+
.JDBC driver dependencies
27+
[%breakable,cols="50,~"]
28+
|===
29+
| Database | Driver dependency
30+
31+
| PostgreSQL or CockroachDB | `org.postgresql:postgresql`
32+
| MySQL or TiDB | `com.mysql:mysql-connector-j`
33+
| MariaDB | `org.mariadb.jdbc:mariadb-java-client`
34+
| DB2 | `com.ibm.db2:jcc`
35+
| SQL Server | `com.microsoft.sqlserver:mssql-jdbc`
36+
| Oracle | `com.oracle.database.jdbc:ojdbc11`
37+
| H2 | `com.h2database:h2`
38+
| HSQLDB | `org.hsqldb:hsqldb`
39+
|===
40+
41+
In addition, we might add some of the following to the mix.
42+
43+
.Optional dependencies
44+
|===
45+
| Optional dependency | Explanation
46+
47+
| `org.hibernate.validator:hibernate-validator` +
48+
and `org.glassfish:jakarta.el` | Hibernate Validator
49+
| `org.apache.logging.log4j:log4j-core` | log4j
50+
| `org.jboss.weld:weld-core-impl` | Weld CDI
51+
|===
52+
53+
You'll need to configure the annotation processor to run when your project is compiled.
54+
In Gradle, for example, you'll need to use `annotationProcessor`.
55+
56+
[source,groovy]
57+
----
58+
annotationProcessor 'org.hibernate.orm:hibernate-jpamodelgen:6.5.0'
59+
----
60+
61+
=== Excluding classes from processing
62+
63+
There's three ways to limit the annotation processor to certain classes:
64+
65+
1. A given repository may be excluded from processing simply by specifying `@Repository(provider="acme")` where `"acme"` is any string other than the empty string or a string equal, ignoring case, to `"Hibernate"`. This is the preferred solution when there are multiple Jakarta Data Providers available.
66+
2. A package or type may be excluded by annotating it with the link:{doc-javadoc-url}org/hibernate/annotations/processing/Exclude.html[`@Exclude`] annotation from `org.hibernate.annotations.processing`.
67+
3. The annotation processor may be limited to consider only certain types or certain packages using the `include` configuration option, for example, `-Ainclude=\*.entity.*,*Repository`. Alternatively, types or packages may be excluded using the `exclude` option, for example, `-Aexclude=*Impl`.
68+
69+
=== Configuring Hibernate ORM
70+
71+
How you configure Hibernate depends on the environment you're running in, and on your preference:
72+
73+
- in Java SE, we often just use `hibernate.properties`, but some people prefer to use `persistence.xml`, especially in case of multiple persistence units,
74+
- in Quarkus, we must use `application.properties`, and
75+
- in a Jakarta EE container, we usually use `persistence.xml`.
76+
77+
Here's a simple `hibernate.properties` file for h2 database, just to get you started.
78+
79+
[source,properties]
80+
----
81+
# Database connection settings
82+
jakarta.persistence.jdbc.url=jdbc:h2:~/h2temp;DB_CLOSE_DELAY=-1
83+
jakarta.persistence.jdbc.user=sa
84+
jakarta.persistence.jdbc.pass=
85+
86+
# Echo all executed SQL to console
87+
hibernate.show_sql=true
88+
hibernate.format_sql=true
89+
hibernate.highlight_sql=true
90+
91+
# Automatically export the schema
92+
hibernate.hbm2ddl.auto=create
93+
----
94+
95+
Please see the link:{doc-introduction-url}#configuration[Introduction to Hibernate 6] for more information about configuring Hibernate.
96+
97+
=== Obtaining a `StatelessSession`
98+
99+
Each repository implementation must somehow obtain a link:{doc-javadoc-url}org/hibernate/StatelessSession.html[`StatelessSession`] for its persistence unit.
100+
This usually happens via dependency injection, so you'll need to make sure that a `StatelessSession` is available for injection:
101+
102+
- in Quarkus, this problem is already taken care of for us--there's always an injectable `StatelessSession` bean for each persistence unit, and
103+
- in a Jakarta EE environment, `HibernateProcessor` generates special code which takes care of creating and destroying the `StatelessSession`, but
104+
- in other environments, this is something we need to take care of ourselves.
105+
106+
[CAUTION]
107+
====
108+
Depending on the libraries in your build path, `HibernateProcessor` generates different code.
109+
For example, if Quarkus is on the build path, the repository implementation is generated to obtain the `StatelessSession` directly from CDI in a way which works in Quarkus but not in WildFly.
110+
====
111+
112+
If you have multiple persistence units, you'll need to disambiguate the persistence unit for a repository interface using `@Repository(dataStore="my-persistence-unit-name")`.
113+
114+
=== Injecting a repository
115+
116+
In principle, any implementation of `jakarta.inject` may be used to inject a repository implementation.
117+
118+
[source,java]
119+
----
120+
@Inject Library library;
121+
----
122+
123+
However, this code will fail if the repository implementation is not able to obtain a `StatelessSession` from the bean container.
124+
125+
It's always possible to instantiate a repository implementation directly.
126+
127+
[source,java]
128+
----
129+
Library library = new Library_(statelessSession);
130+
----
131+
132+
This is useful for testing, or for executing in an environment with no support for `jakarta.inject`.
133+
134+
=== Integration with Jakarta EE
135+
136+
Jakarta Data specifies that methods of a repository interface may be annotated with:
137+
138+
- Jakarta Bean Validation constraint annotations, and
139+
- Jakarta Interceptors interceptor binding types, including,
140+
- in particular, the `@Transactional` interceptor binding defined by Jakarta Transactions.
141+
142+
Note that these annotations are usually applied to a CDI bean implementation class, not to an interface,footnote:[`@Inherited` annotations are inherited from superclass to subclass, but not from interface to implementing class.] but a special exception is made for repository interfaces.
143+
144+
Therefore, when running in a Jakarta EE environment, or in Quarkus, and when an instance of a repository interface is obtained via CDI, the semantics of such annotations is respected.
145+
146+
[source,java]
147+
----
148+
@Transactional @Repository
149+
public interface Library {
150+
151+
@Find
152+
Book book(@NotNull String isbn);
153+
154+
@Find
155+
Book book(@NotBlank String title, @NotNull LocalDate publicationDate);
156+
157+
}
158+
----
159+
160+
As an aside, it's rather satisfying to see all these things working so nicely together, since we members of the Hibernate team played pivotal roles in the creation of the Persistence, Bean Validation, CDI, Interceptors, and Data specifications.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
:shared-attributes-dir: ../shared/
2+
3+
include::{shared-attributes-dir}/common-attributes.adoc[]
4+
include::{shared-attributes-dir}/url-attributes.adoc[]
5+
include::{shared-attributes-dir}/filesystem-attributes.adoc[]
6+
include::{shared-attributes-dir}/renderer-attributes.adoc[]
7+
8+
= Introducing Hibernate Data Repositories
9+
:title-logo-image: image:../../style/asciidoctor/images/org/hibernate/logo.png[]
10+
:toc:
11+
:toclevels: 3
12+
13+
include::Preface.adoc[]
14+
15+
:numbered:
16+
17+
include::Repositories.adoc[]
18+
include::Configuration.adoc[]
19+
include::Pagination.adoc[]
20+
21+

0 commit comments

Comments
 (0)