diff --git a/004-quarkus-HHH-and-HV/README.md b/004-quarkus-HHH-and-HV/README.md index 844bdb77..b1c6047d 100644 --- a/004-quarkus-HHH-and-HV/README.md +++ b/004-quarkus-HHH-and-HV/README.md @@ -1,3 +1,7 @@ # Quarkus - Hibernate and Hibernate Validator (lazy fetch strategy) This scenario uses in-memory Java database H2. -Test class annotated with `@QuarkusTestResource(H2DatabaseTestResource.class)` starts an in-memory H2 database \ No newline at end of file +Test class annotated with `@QuarkusTestResource(H2DatabaseTestResource.class)` starts an in-memory H2 database + +Module that covers intergation with some Hibernate features like: +- Usage of Code Generator: `hibernate-jpamodelgen` dependency +- Reproducer for [14201](https://github.com/quarkusio/quarkus/issues/14201) and [14881](https://github.com/quarkusio/quarkus/issues/14881): possible data loss bug in hibernate \ No newline at end of file diff --git a/004-quarkus-HHH-and-HV/pom.xml b/004-quarkus-HHH-and-HV/pom.xml index d1804e35..6cdc5462 100644 --- a/004-quarkus-HHH-and-HV/pom.xml +++ b/004-quarkus-HHH-and-HV/pom.xml @@ -38,6 +38,11 @@ io.quarkus quarkus-hibernate-validator + + org.hibernate + hibernate-jpamodelgen + provided + io.quarkus quarkus-test-h2 diff --git a/004-quarkus-HHH-and-HV/src/main/java/io/quarkus/qe/hibernate/items/Account.java b/004-quarkus-HHH-and-HV/src/main/java/io/quarkus/qe/hibernate/items/Account.java new file mode 100644 index 00000000..17d4c5c1 --- /dev/null +++ b/004-quarkus-HHH-and-HV/src/main/java/io/quarkus/qe/hibernate/items/Account.java @@ -0,0 +1,37 @@ +package io.quarkus.qe.hibernate.items; + +import java.util.Date; +import java.util.HashSet; +import java.util.Set; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.JoinTable; +import javax.persistence.ManyToMany; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; + +@Entity +public class Account { + + @Id + public Long id; + + @Column(length = 255, unique = true, nullable = false) + @NotNull + @Size(max = 255) + public String email; + + @Temporal(TemporalType.TIMESTAMP) + public Date createdOn; + + @ManyToMany(fetch = FetchType.LAZY) + @JoinTable(name = "account_in_role", joinColumns = @JoinColumn(name = "accountid"), inverseJoinColumns = @JoinColumn(name = "roleid")) + public Set roles = new HashSet<>(); + +} diff --git a/004-quarkus-HHH-and-HV/src/main/java/io/quarkus/qe/hibernate/items/Customer.java b/004-quarkus-HHH-and-HV/src/main/java/io/quarkus/qe/hibernate/items/Customer.java new file mode 100644 index 00000000..795ff457 --- /dev/null +++ b/004-quarkus-HHH-and-HV/src/main/java/io/quarkus/qe/hibernate/items/Customer.java @@ -0,0 +1,32 @@ +package io.quarkus.qe.hibernate.items; + +import java.util.Date; + +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.Id; +import javax.persistence.OneToOne; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; +import javax.persistence.Version; + +@Entity +public class Customer { + + @Id + public Long id; + + @Version + @Column(name = "version") + public int version; + + @Temporal(TemporalType.TIMESTAMP) + public Date createdOn; + + @OneToOne(optional = false, fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE}) + public Account account; + + +} \ No newline at end of file diff --git a/004-quarkus-HHH-and-HV/src/main/java/io/quarkus/qe/hibernate/items/Item.java b/004-quarkus-HHH-and-HV/src/main/java/io/quarkus/qe/hibernate/items/Item.java new file mode 100644 index 00000000..9c0a78b3 --- /dev/null +++ b/004-quarkus-HHH-and-HV/src/main/java/io/quarkus/qe/hibernate/items/Item.java @@ -0,0 +1,21 @@ +package io.quarkus.qe.hibernate.items; + +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; + +@Entity +public class Item { + + @Id + public Long id; + + public String note; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "customerId") + public Customer customer; + +} diff --git a/004-quarkus-HHH-and-HV/src/main/java/io/quarkus/qe/hibernate/items/ItemsResource.java b/004-quarkus-HHH-and-HV/src/main/java/io/quarkus/qe/hibernate/items/ItemsResource.java new file mode 100644 index 00000000..747cf057 --- /dev/null +++ b/004-quarkus-HHH-and-HV/src/main/java/io/quarkus/qe/hibernate/items/ItemsResource.java @@ -0,0 +1,33 @@ +package io.quarkus.qe.hibernate.items; + +import javax.inject.Inject; +import javax.persistence.EntityManager; +import javax.persistence.TypedQuery; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Join; +import javax.persistence.criteria.Root; +import javax.transaction.Transactional; +import javax.ws.rs.GET; +import javax.ws.rs.Path; + +@Path("/items") +@Transactional +public class ItemsResource { + + @Inject + EntityManager em; + + @GET + @Path("/count") + public int countOrders() { + CriteriaBuilder cb = em.getCriteriaBuilder(); + CriteriaQuery cq = cb.createQuery(Item.class); + Root root = cq.from(Item.class); + Join custJoin = (Join) root.fetch(Item_.customer); + + TypedQuery query = em.createQuery(cq); + return query.getResultList().size(); + } + +} diff --git a/004-quarkus-HHH-and-HV/src/main/java/io/quarkus/qe/hibernate/items/Role.java b/004-quarkus-HHH-and-HV/src/main/java/io/quarkus/qe/hibernate/items/Role.java new file mode 100644 index 00000000..a1dcff87 --- /dev/null +++ b/004-quarkus-HHH-and-HV/src/main/java/io/quarkus/qe/hibernate/items/Role.java @@ -0,0 +1,16 @@ +package io.quarkus.qe.hibernate.items; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; + +@Entity +public class Role { + + @Id + public Long id; + + @Column + public String name; + +} \ No newline at end of file diff --git a/004-quarkus-HHH-and-HV/src/main/resources/application.properties b/004-quarkus-HHH-and-HV/src/main/resources/application.properties index 93f79a85..fd8e4138 100644 --- a/004-quarkus-HHH-and-HV/src/main/resources/application.properties +++ b/004-quarkus-HHH-and-HV/src/main/resources/application.properties @@ -3,4 +3,5 @@ quarkus.datasource.jdbc.url=jdbc:h2:tcp://localhost/mem:test quarkus.hibernate-orm.dialect=org.hibernate.dialect.H2Dialect quarkus.datasource.jdbc.min-size=3 quarkus.datasource.jdbc.max-size=10 -quarkus.hibernate-orm.database.generation=drop-and-create \ No newline at end of file +quarkus.hibernate-orm.database.generation=drop-and-create +quarkus.hibernate-orm.sql-load-script=import.sql \ No newline at end of file diff --git a/004-quarkus-HHH-and-HV/src/main/resources/import.sql b/004-quarkus-HHH-and-HV/src/main/resources/import.sql new file mode 100644 index 00000000..84a30fc4 --- /dev/null +++ b/004-quarkus-HHH-and-HV/src/main/resources/import.sql @@ -0,0 +1,12 @@ +truncate table item cascade ; +truncate table customer cascade ; +truncate table account_in_role cascade ; +truncate table account cascade ; +truncate table role cascade ; +start TRANSACTION ; +insert into account (id, email) values (1, 'foo@bar.com'); +insert into role (id, name) values (1, 'admin'); +insert into account_in_role (accountid, roleid) values (1, 1); +insert into customer (id, version, account_id) values (1, 1, 1); +insert into item (id, note, customerid) values (1, 'Item 1', 1); +commit; \ No newline at end of file diff --git a/004-quarkus-HHH-and-HV/src/test/java/io/quarkus/qe/hibernate/items/ItemsResourceTest.java b/004-quarkus-HHH-and-HV/src/test/java/io/quarkus/qe/hibernate/items/ItemsResourceTest.java new file mode 100644 index 00000000..973ef49d --- /dev/null +++ b/004-quarkus-HHH-and-HV/src/test/java/io/quarkus/qe/hibernate/items/ItemsResourceTest.java @@ -0,0 +1,20 @@ +package io.quarkus.qe.hibernate.items; + +import static io.restassured.RestAssured.given; +import static org.hamcrest.Matchers.is; + +import org.junit.jupiter.api.Test; + +import io.quarkus.test.junit.QuarkusTest; + +@QuarkusTest +public class ItemsResourceTest { + + /** + * Required data is pulled in from the `import.sql` resource. + */ + @Test + public void shouldNotFailWithConstraints() { + given().when().get("/items/count").then().body(is("1")); + } +} diff --git a/004-quarkus-HHH-and-HV/src/test/java/io/quarkus/qe/hibernate/items/NativeItemsResourceIT.java b/004-quarkus-HHH-and-HV/src/test/java/io/quarkus/qe/hibernate/items/NativeItemsResourceIT.java new file mode 100644 index 00000000..47ecccca --- /dev/null +++ b/004-quarkus-HHH-and-HV/src/test/java/io/quarkus/qe/hibernate/items/NativeItemsResourceIT.java @@ -0,0 +1,7 @@ +package io.quarkus.qe.hibernate.items; + +import io.quarkus.test.junit.NativeImageTest; + +@NativeImageTest +public class NativeItemsResourceIT extends ItemsResourceTest { +}