@@ -1646,3 +1646,134 @@ try {
16461646Since Quarkus has built-in exception mappers for `jakarta.validation.ConstraintViolationException`,
16471647explicitly handling these exceptions might be redundant. See the xref:validation.adoc#rest-end-point-validation[REST end point validation]
16481648section of the Hibernate Validator guide for more details.
1649+
1650+ [[jakarta-data]]
1651+ == Static metamodel and Jakarta Data
1652+
1653+ Both static metamodel and Jakarta Data capabilities of Hibernate ORM are available in Quarkus
1654+ through the `hibernate-jpamodelgen` annotation processor. Since it is an annotation processor,
1655+ you must configure the annotation processor in your build tool:
1656+
1657+ [source,xml,role="primary asciidoc-tabs-target-sync-cli asciidoc-tabs-target-sync-maven"]
1658+ .pom.xml
1659+ ----
1660+ <plugin>
1661+ <artifactId>maven-compiler-plugin</artifactId>
1662+ <configuration>
1663+ <annotationProcessorPaths>
1664+ <path>
1665+ <groupId>org.hibernate.orm</groupId>
1666+ <artifactId>hibernate-jpamodelgen</artifactId>
1667+ <!-- Note, no artifact version is required, it's managed by Quarkus. -->
1668+ </path>
1669+ <!-- other processors that may be required by your app -->
1670+ </annotationProcessorPaths>
1671+ <!-- Other compiler plugin configuration options -->
1672+ </configuration>
1673+ </plugin>
1674+ ----
1675+
1676+ [source,gradle,role="secondary asciidoc-tabs-target-sync-gradle"]
1677+ .build.gradle
1678+ ----
1679+ // Enforce the version management of your annotation processor dependencies,
1680+ // so that there's no need to define an explicit version of the hibernate-jpamodelgen
1681+ annotationProcessor enforcedPlatform("${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:${quarkusPlatformVersion}")
1682+ annotationProcessor 'org.hibernate.orm:hibernate-jpamodelgen'
1683+ ----
1684+
1685+ === Static metamodel
1686+
1687+ The generated static metamodel allows for building queries in a type-safe manner.
1688+ Let's consider having a simple entity:
1689+
1690+ [source,java]
1691+ ----
1692+ @Entity
1693+ public class MyEntity {
1694+ @Id
1695+ @GeneratedValue
1696+ public Integer id;
1697+
1698+ @Column(unique = true)
1699+ public String name;
1700+ }
1701+ ----
1702+
1703+ A query created with the help of static metamodel may look as:
1704+
1705+ [source,java]
1706+ ----
1707+ var builder = session.getCriteriaBuilder();
1708+ var criteria = builder.createQuery(MyEntity.class);
1709+ var e = criteria.from(MyEntity_.class);
1710+ criteria.where(e.get(MyEntity_.name).equalTo(name));
1711+ var query = session.createQuery(criteria);
1712+ var result = query.list();
1713+ ----
1714+
1715+ For a more detailed overview of static metamodel, please refer to the link:{jakarta-persistence-spec-url}#a6072[Jakarta Persistence specification].
1716+
1717+ === Jakarta Data
1718+
1719+ Jakarta Data requires, besides having the `hibernate-jpamodelgen` annotation processor in place, one extra dependency to be added:
1720+
1721+ [source,xml,role="primary asciidoc-tabs-target-sync-cli asciidoc-tabs-target-sync-maven"]
1722+ .pom.xml
1723+ ----
1724+ <dependency>
1725+ <groupId>jakarta.data</groupId>
1726+ <artifactId>jakarta.data-api</artifactId>
1727+ </dependency>
1728+ ----
1729+
1730+ [source,gradle,role="secondary asciidoc-tabs-target-sync-gradle"]
1731+ .build.gradle
1732+ ----
1733+ implementation 'jakarta.data:jakarta.data-api'
1734+ ----
1735+
1736+ With this dependency, and the annotation processor in place you could simply create your repositories as follows:
1737+
1738+ [source,java]
1739+ ----
1740+ @Repository
1741+ public interface MyRepository extends CrudRepository<MyEntity, Integer> { // <1>
1742+
1743+ @Query("select e from MyEntity e where e.name like :name") // <2>
1744+ List<MyEntity> findByName(String name);
1745+
1746+ @Delete // <3>
1747+ void delete(String name);
1748+
1749+ }
1750+ ----
1751+ 1. To skip the boilerplate definition of CRUD operations,
1752+ we can use one of the available interfaces (e.g. `CrudRepository` or `BasicRepository`).
1753+ 2. Adding custom queries with parameters is as easy as providing your query string to the `@Query` annotation.
1754+ 3. If the basic CRUD operations from the Jakarta Data interfaces are not enough,
1755+ we can always add a custom one, in this case a delete operation that removes `MyEntity`s by name.
1756+
1757+ And then the repository can be used as any other bean:
1758+
1759+ [source,java]
1760+ ----
1761+ public class MyEntityResource {
1762+
1763+ @Inject
1764+ MyRepository repository;
1765+
1766+ @POST
1767+ @Transactional
1768+ public void create(MyEntity entity) {
1769+ repository.insert(entity);
1770+ }
1771+
1772+ // ...
1773+
1774+ }
1775+ ----
1776+
1777+ Please refer to the corresponding https://hibernate.org/repositories/[Hibernate Data Repositories]
1778+ and https://jakarta.ee/specifications/data/1.0/jakarta-data-1.0[Jakarta Data]
1779+ guides to learn what else they have to offer.
0 commit comments