|
| 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. |
0 commit comments