Skip to content

Commit f071db3

Browse files
authored
Merge pull request #47012 from marko-bekhta/feat/i44278-add-jakarta-data-tests
Add Jakarta Data documentation, dependency management and tests
2 parents 62c2cc1 + cc55044 commit f071db3

File tree

13 files changed

+490
-1
lines changed

13 files changed

+490
-1
lines changed

bom/application/pom.xml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,8 @@
7171
<jakarta.json-api.version>2.1.3</jakarta.json-api.version>
7272
<jakarta.json.bind-api.version>3.0.1</jakarta.json.bind-api.version>
7373
<jakarta.mail-api.version>2.1.3</jakarta.mail-api.version>
74-
<jakarta.persistence-api.version>3.1.0</jakarta.persistence-api.version>
74+
<!--jakarta.persistence-api.version is located in the root pom -->
75+
<jakarta.data-api.version>1.0.1</jakarta.data-api.version>
7576
<jakarta.resource-api.version>2.1.0</jakarta.resource-api.version>
7677
<jakarta.servlet-api.version>6.0.0</jakarta.servlet-api.version>
7778
<jakarta.transaction-api.version>2.0.1</jakarta.transaction-api.version>
@@ -4390,6 +4391,11 @@
43904391
<artifactId>jakarta.persistence-api</artifactId>
43914392
<version>${jakarta.persistence-api.version}</version>
43924393
</dependency>
4394+
<dependency>
4395+
<groupId>jakarta.data</groupId>
4396+
<artifactId>jakarta.data-api</artifactId>
4397+
<version>${jakarta.data-api.version}</version>
4398+
</dependency>
43934399
<dependency>
43944400
<groupId>jakarta.resource</groupId>
43954401
<artifactId>jakarta.resource-api</artifactId>

docs/pom.xml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3230,6 +3230,17 @@
32303230
<versionString>${hibernate-validator.version}</versionString>
32313231
</configuration>
32323232
</execution>
3233+
<execution>
3234+
<id>parse-version-jakarta-persistence</id>
3235+
<goals>
3236+
<goal>parse-version</goal>
3237+
</goals>
3238+
<phase>validate</phase>
3239+
<configuration>
3240+
<propertyPrefix>jakarta-persistence</propertyPrefix>
3241+
<versionString>${jakarta.persistence-api.version}</versionString>
3242+
</configuration>
3243+
</execution>
32333244
</executions>
32343245
</plugin>
32353246
<plugin>

docs/src/main/asciidoc/_attributes.adoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
:hibernate-orm-version-major-minor: ${hibernate-orm.majorVersion}.${hibernate-orm.minorVersion}
3131
:hibernate-search-version-major-minor: ${hibernate-search.majorVersion}.${hibernate-search.minorVersion}
3232
:hibernate-validator-version-major-minor: ${hibernate-validator.majorVersion}.${hibernate-validator.minorVersion}
33+
:jakarta-persistence-version-major-minor: ${jakarta-persistence.majorVersion}.${jakarta-persistence.minorVersion}
3334
// .
3435
:quarkus-home-url: ${quarkus-home-url}
3536
:quarkus-org-url: https://github.com/quarkusio
@@ -56,6 +57,7 @@
5657
:hibernate-orm-dialect-docs-url: https://docs.jboss.org/hibernate/orm/{hibernate-orm-version-major-minor}/dialect/dialect.html
5758
:hibernate-search-docs-url: https://docs.jboss.org/hibernate/search/{hibernate-search-version-major-minor}/reference/en-US/html_single/
5859
:hibernate-validator-docs-url: https://docs.jboss.org/hibernate/validator/{hibernate-validator-version-major-minor}/reference/en-US/html_single/
60+
:jakarta-persistence-spec-url: https://jakarta.ee/specifications/persistence/{jakarta-persistence-version-major-minor}/jakarta-persistence-spec-{jakarta-persistence-version-major-minor}#a6072
5961
// .
6062
:amazon-services-guide: https://docs.quarkiverse.io/quarkus-amazon-services/dev/index.html
6163
:config-consul-guide: https://docs.quarkiverse.io/quarkus-config-extensions/dev/consul.html

docs/src/main/asciidoc/hibernate-orm.adoc

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1646,3 +1646,134 @@ try {
16461646
Since Quarkus has built-in exception mappers for `jakarta.validation.ConstraintViolationException`,
16471647
explicitly handling these exceptions might be redundant. See the xref:validation.adoc#rest-end-point-validation[REST end point validation]
16481648
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.
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<parent>
6+
<artifactId>quarkus-integration-tests-parent</artifactId>
7+
<groupId>io.quarkus</groupId>
8+
<version>999-SNAPSHOT</version>
9+
</parent>
10+
<modelVersion>4.0.0</modelVersion>
11+
12+
<artifactId>quarkus-integration-test-hibernate-orm-data</artifactId>
13+
<name>Quarkus - Integration Tests - Hibernate ORM with Jakarta Data</name>
14+
15+
<dependencies>
16+
<dependency>
17+
<groupId>io.quarkus</groupId>
18+
<artifactId>quarkus-hibernate-orm</artifactId>
19+
</dependency>
20+
<dependency>
21+
<groupId>jakarta.data</groupId>
22+
<artifactId>jakarta.data-api</artifactId>
23+
</dependency>
24+
<dependency>
25+
<groupId>io.quarkus</groupId>
26+
<artifactId>quarkus-rest</artifactId>
27+
</dependency>
28+
<dependency>
29+
<groupId>io.quarkus</groupId>
30+
<artifactId>quarkus-rest-jackson</artifactId>
31+
</dependency>
32+
<dependency>
33+
<groupId>io.quarkus</groupId>
34+
<artifactId>quarkus-jdbc-h2</artifactId>
35+
</dependency>
36+
37+
<!-- test dependencies -->
38+
<dependency>
39+
<groupId>io.quarkus</groupId>
40+
<artifactId>quarkus-junit5</artifactId>
41+
<scope>test</scope>
42+
</dependency>
43+
<dependency>
44+
<groupId>io.quarkus</groupId>
45+
<artifactId>quarkus-junit5-internal</artifactId>
46+
<scope>test</scope>
47+
</dependency>
48+
<dependency>
49+
<groupId>io.rest-assured</groupId>
50+
<artifactId>rest-assured</artifactId>
51+
<scope>test</scope>
52+
</dependency>
53+
<dependency>
54+
<groupId>org.assertj</groupId>
55+
<artifactId>assertj-core</artifactId>
56+
<scope>test</scope>
57+
</dependency>
58+
59+
<!-- Minimal test dependencies to *-deployment artifacts for consistent build order -->
60+
<dependency>
61+
<groupId>io.quarkus</groupId>
62+
<artifactId>quarkus-hibernate-orm-deployment</artifactId>
63+
<version>${project.version}</version>
64+
<type>pom</type>
65+
<scope>test</scope>
66+
<exclusions>
67+
<exclusion>
68+
<groupId>*</groupId>
69+
<artifactId>*</artifactId>
70+
</exclusion>
71+
</exclusions>
72+
</dependency>
73+
<dependency>
74+
<groupId>io.quarkus</groupId>
75+
<artifactId>quarkus-jdbc-h2-deployment</artifactId>
76+
<version>${project.version}</version>
77+
<type>pom</type>
78+
<scope>test</scope>
79+
<exclusions>
80+
<exclusion>
81+
<groupId>*</groupId>
82+
<artifactId>*</artifactId>
83+
</exclusion>
84+
</exclusions>
85+
</dependency>
86+
<dependency>
87+
<groupId>io.quarkus</groupId>
88+
<artifactId>quarkus-rest-deployment</artifactId>
89+
<version>${project.version}</version>
90+
<type>pom</type>
91+
<scope>test</scope>
92+
<exclusions>
93+
<exclusion>
94+
<groupId>*</groupId>
95+
<artifactId>*</artifactId>
96+
</exclusion>
97+
</exclusions>
98+
</dependency>
99+
<dependency>
100+
<groupId>io.quarkus</groupId>
101+
<artifactId>quarkus-rest-jackson-deployment</artifactId>
102+
<version>${project.version}</version>
103+
<type>pom</type>
104+
<scope>test</scope>
105+
<exclusions>
106+
<exclusion>
107+
<groupId>*</groupId>
108+
<artifactId>*</artifactId>
109+
</exclusion>
110+
</exclusions>
111+
</dependency>
112+
</dependencies>
113+
114+
<build>
115+
<resources>
116+
<resource>
117+
<directory>src/main/resources</directory>
118+
<filtering>true</filtering>
119+
</resource>
120+
</resources>
121+
<plugins>
122+
<plugin>
123+
<groupId>io.quarkus</groupId>
124+
<artifactId>quarkus-maven-plugin</artifactId>
125+
<executions>
126+
<execution>
127+
<goals>
128+
<goal>build</goal>
129+
</goals>
130+
</execution>
131+
</executions>
132+
</plugin>
133+
<plugin>
134+
<artifactId>maven-compiler-plugin</artifactId>
135+
<configuration>
136+
<annotationProcessorPaths>
137+
<path>
138+
<groupId>org.hibernate.orm</groupId>
139+
<artifactId>hibernate-jpamodelgen</artifactId>
140+
</path>
141+
</annotationProcessorPaths>
142+
</configuration>
143+
</plugin>
144+
</plugins>
145+
</build>
146+
147+
148+
</project>
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package io.quarkus.it.hibernate.jpamodelgen.data;
2+
3+
import jakarta.persistence.Column;
4+
import jakarta.persistence.Entity;
5+
import jakarta.persistence.GeneratedValue;
6+
import jakarta.persistence.Id;
7+
8+
@Entity
9+
public class MyEntity {
10+
11+
@Id
12+
@GeneratedValue
13+
public Integer id;
14+
15+
@Column(unique = true)
16+
public String name;
17+
18+
MyEntity() {
19+
}
20+
21+
public MyEntity(String name) {
22+
this.name = name;
23+
}
24+
25+
@Override
26+
public String toString() {
27+
return "MyOrmEntity [id=" + id + ", name=" + name + "]";
28+
}
29+
30+
}

0 commit comments

Comments
 (0)