@@ -1646,3 +1646,134 @@ try {
1646
1646
Since Quarkus has built-in exception mappers for `jakarta.validation.ConstraintViolationException`,
1647
1647
explicitly handling these exceptions might be redundant. See the xref:validation.adoc#rest-end-point-validation[REST end point validation]
1648
1648
section 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