@@ -1569,3 +1569,134 @@ Format mappers *must* have both `@PersistenceUnitExtension` and either `@JsonFor
15691569
15701570Having multiple JSON (or XML) format mappers registered for the same persistence unit will result in an exception, because of the ambiguity.
15711571====
1572+
1573+ [[jakarta-data]]
1574+ == Static metamodel and Jakarta Data
1575+
1576+ Both static metamodel and Jakarta Data capabilities of Hibernate ORM are available to the users
1577+ through the `hibernate-jpamodelgen` annotation processor. Since it is an annotation processor,
1578+ users are required to make an extra step of configuring the annotation processor in their build tool of choice:
1579+
1580+ [source,xml,role="primary asciidoc-tabs-target-sync-cli asciidoc-tabs-target-sync-maven"]
1581+ .pom.xml
1582+ ----
1583+ <plugin>
1584+ <artifactId>maven-compiler-plugin</artifactId>
1585+ <configuration>
1586+ <annotationProcessorPaths>
1587+ <path>
1588+ <groupId>org.hibernate.orm</groupId>
1589+ <artifactId>hibernate-jpamodelgen</artifactId>
1590+ <!-- Note, no artifact version is required, it's managed by Quarkus. -->
1591+ </path>
1592+ <!-- other processors that may be required by your app -->
1593+ </annotationProcessorPaths>
1594+ <!-- Other compiler plugin configuration options -->
1595+ </configuration>
1596+ </plugin>
1597+ ----
1598+
1599+ [source,gradle,role="secondary asciidoc-tabs-target-sync-gradle"]
1600+ .build.gradle
1601+ ----
1602+ // Enforce the version management of your annotation processor dependencies,
1603+ // so that there's no need to define an explicit version of the hibernate-jpamodelgen
1604+ annotationProcessor enforcedPlatform("${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:${quarkusPlatformVersion}")
1605+ annotationProcessor 'org.hibernate.orm:hibernate-jpamodelgen'
1606+ ----
1607+
1608+ === Static metamodel
1609+
1610+ The generated static metamodel allows for building queries in a type-safe manner.
1611+ Let's consider having a simple entity:
1612+
1613+ [source,java]
1614+ ----
1615+ @Entity
1616+ public class MyEntity {
1617+ @Id
1618+ @GeneratedValue
1619+ public Integer id;
1620+
1621+ @Column(unique = true)
1622+ public String name;
1623+ }
1624+ ----
1625+
1626+ A query created with the help of static metamodel may look as:
1627+
1628+ [source,java]
1629+ ----
1630+ var builder = session.getCriteriaBuilder();
1631+ var query = builder.createQuery(MyEntity.class);
1632+ var e = query.from(MyEntity_.class);
1633+ query.where(e.get(MyEntity_.name).equalTo(name));
1634+ session.createQuery(query)....
1635+ ----
1636+
1637+ For a more detailed overview of static metamodel, please refer to the link:{jakarta-persistence-spec-url}#a6072[Jakarta Persistence specification].
1638+
1639+ === Jakarta Data
1640+
1641+ Jakarta Data requires, besides having the `hibernate-jpamodelgen` annotation processor in place, one extra dependency to be added:
1642+
1643+ [source,xml,role="primary asciidoc-tabs-target-sync-cli asciidoc-tabs-target-sync-maven"]
1644+ .pom.xml
1645+ ----
1646+ <dependency>
1647+ <groupId>jakarta.data</groupId>
1648+ <artifactId>jakarta.data-api</artifactId>
1649+ </dependency>
1650+ ----
1651+
1652+ [source,gradle,role="secondary asciidoc-tabs-target-sync-gradle"]
1653+ .build.gradle
1654+ ----
1655+ implementation 'jakarta.data:jakarta.data-api'
1656+ ----
1657+
1658+ With this dependency, and the annotation processor in place you could simply create your repositories as follows:
1659+
1660+ [source,java]
1661+ ----
1662+ @Repository
1663+ public interface MyRepository extends CrudRepository<MyEntity, Integer> { // <1>
1664+
1665+ @Query("select e from MyEntity e where e.name like :name") // <2>
1666+ List<MyEntity> findByName(String name);
1667+
1668+ @Delete // <3>
1669+ void delete(String name);
1670+
1671+ }
1672+ ----
1673+ 1. To skip the boilerplate definition of CRUD operations,
1674+ we can use one of the available interfaces (e.g. `CrudRepository` or `BasicRepository`).
1675+ 2. Adding custom queries with parameters is as easy as providing your query string to the `@Query` annotation.
1676+ 3. If the basic CRUD operations from the Jakarta Data interfaces are not enough,
1677+ we can always add a custom one, in this case a delete operation that removes `MyEntity`s by name.
1678+
1679+ And then the repository can be used as any other bean:
1680+
1681+ [source,java]
1682+ ----
1683+ public class MyEntityResource {
1684+
1685+ @Inject
1686+ MyRepository repository;
1687+
1688+ @POST
1689+ @Transactional
1690+ public void create(MyEntity entity) {
1691+ repository.insert(entity);
1692+ }
1693+
1694+ // ...
1695+
1696+ }
1697+ ----
1698+
1699+ Please refer to the corresponding https://hibernate.org/repositories/[Hibernate Data Repositories]
1700+ and https://jakarta.ee/specifications/data/1.0/jakarta-data-1.0[Jakarta Data]
1701+ guides to learn what else they have to offer.
1702+
0 commit comments