Skip to content

Commit

Permalink
Use a more Quarkus-native style for JPA tests
Browse files Browse the repository at this point in the history
1. Inject the entity manager and make use of the transaction-scoped
   entity manager proxy.
2. Use QuarkusTransaction instead of em.getTransaction() (which isn't
   even supposed to work in JTA environments...)
  • Loading branch information
yrodiere committed Dec 4, 2023
1 parent 25588d8 commit 861e286
Show file tree
Hide file tree
Showing 11 changed files with 606 additions and 1,058 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@

import jakarta.inject.Inject;
import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.EntityTransaction;
import jakarta.persistence.TypedQuery;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;
Expand All @@ -17,6 +15,8 @@
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;

import io.quarkus.narayana.jta.QuarkusTransaction;

/**
* Various tests covering JPA functionality. All tests should work in both standard JVM and native mode.
*/
Expand All @@ -25,105 +25,74 @@
public class JPAFunctionalityTestEndpoint {

@Inject
EntityManagerFactory entityManagerFactory;
EntityManager em;

@GET
public String test() throws IOException {
//Cleanup any existing data:
deleteAllPerson(entityManagerFactory);
cleanUpData();

//Store some well known Person instances we can then test on:
storeTestPersons(entityManagerFactory);
QuarkusTransaction.requiringNew().run(() -> {
persistNewPerson("Gizmo");
persistNewPerson("Quarkus");
persistNewPerson("Hibernate ORM");
});

//Load all persons and run some checks on the query results:
verifyListOfExistingPersons(entityManagerFactory);
QuarkusTransaction.requiringNew().run(() -> {
CriteriaBuilder cb = em.getCriteriaBuilder();

CriteriaQuery<Person> cq = cb.createQuery(Person.class);
Root<Person> from = cq.from(Person.class);
cq.select(from).orderBy(cb.asc(from.get("name")));
TypedQuery<Person> q = em.createQuery(cq);
List<Person> allpersons = q.getResultList();
if (allpersons.size() != 3) {
throw new RuntimeException("Incorrect number of results");
}
if (!allpersons.get(0).getName().equals("Gizmo")) {
throw new RuntimeException("Incorrect order of results");
}
StringBuilder sb = new StringBuilder("list of stored Person names:\n\t");
for (Person p : allpersons) {
p.describeFully(sb);
sb.append("\n\t");
if (p.getStatus() != Status.LIVING) {
throw new RuntimeException("Incorrect status " + p);
}
}
sb.append("\nList complete.\n");
System.out.print(sb);
});

//Try a JPA named query:
verifyJPANamedQuery(entityManagerFactory);
QuarkusTransaction.requiringNew().run(() -> {
TypedQuery<Person> typedQuery = em.createNamedQuery(
"get_person_by_name", Person.class);
typedQuery.setParameter("name", "Quarkus");
final Person singleResult = typedQuery.getSingleResult();

if (!singleResult.getName().equals("Quarkus")) {
throw new RuntimeException("Wrong result from named JPA query");
}
});

deleteAllPerson(entityManagerFactory);
cleanUpData();

return "OK";
}

private static void verifyJPANamedQuery(final EntityManagerFactory emf) {
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin();
TypedQuery<Person> typedQuery = em.createNamedQuery(
"get_person_by_name", Person.class);
typedQuery.setParameter("name", "Quarkus");
final Person singleResult = typedQuery.getSingleResult();

if (!singleResult.getName().equals("Quarkus")) {
throw new RuntimeException("Wrong result from named JPA query");
}

transaction.commit();
em.close();
}

private static void verifyListOfExistingPersons(final EntityManagerFactory emf) {
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin();
listExistingPersons(em);
transaction.commit();
em.close();
}

private static void storeTestPersons(final EntityManagerFactory emf) {
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin();
persistNewPerson(em, "Gizmo");
persistNewPerson(em, "Quarkus");
persistNewPerson(em, "Hibernate ORM");
transaction.commit();
em.close();
}

private static void deleteAllPerson(final EntityManagerFactory emf) {
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin();
em.createNativeQuery("Delete from Person").executeUpdate();
transaction.commit();
em.close();
}

private static void listExistingPersons(EntityManager em) {
CriteriaBuilder cb = em.getCriteriaBuilder();

CriteriaQuery<Person> cq = cb.createQuery(Person.class);
Root<Person> from = cq.from(Person.class);
cq.select(from).orderBy(cb.asc(from.get("name")));
TypedQuery<Person> q = em.createQuery(cq);
List<Person> allpersons = q.getResultList();
if (allpersons.size() != 3) {
throw new RuntimeException("Incorrect number of results");
}
if (!allpersons.get(0).getName().equals("Gizmo")) {
throw new RuntimeException("Incorrect order of results");
}
StringBuilder sb = new StringBuilder("list of stored Person names:\n\t");
for (Person p : allpersons) {
p.describeFully(sb);
sb.append("\n\t");
if (p.getStatus() != Status.LIVING) {
throw new RuntimeException("Incorrect status " + p);
}
}
sb.append("\nList complete.\n");
System.out.print(sb);
private void cleanUpData() {
QuarkusTransaction.requiringNew()
.run(() -> em.createNativeQuery("Delete from Person").executeUpdate());
}

private static void persistNewPerson(EntityManager entityManager, String name) {
private void persistNewPerson(String name) {
Person person = new Person();
person.setName(name);
person.setStatus(Status.LIVING);
person.setAddress(new SequencedAddress("Street " + randomName()));
entityManager.persist(person);
em.persist(person);
}

private static String randomName() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@

import jakarta.inject.Inject;
import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.EntityTransaction;
import jakarta.persistence.TypedQuery;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;
Expand All @@ -16,129 +14,84 @@
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;

import io.quarkus.narayana.jta.QuarkusTransaction;

/**
* Basic test running JPA with the Derby database.
* The application can work in either standard JVM or in native mode, while we run H2 as a separate JVM process.
* The application can work in either standard JVM or in native mode, while we run Derby as a separate JVM process.
*/
@Path("/jpa-derby/testfunctionality")
@Produces(MediaType.TEXT_PLAIN)
public class JPAFunctionalityTestEndpoint {

@Inject
EntityManagerFactory entityManagerFactory;
EntityManager em;

@GET
public String test() {
//Cleanup any existing data:
deleteAllPerson(entityManagerFactory);
cleanUpData();

//Store some well known Person instances we can then test on:
storeTestPersons(entityManagerFactory);
QuarkusTransaction.requiringNew().run(() -> {
persistNewPerson("Gizmo");
persistNewPerson("Quarkus");
persistNewPerson("Hibernate ORM");
});

//Load all persons and run some checks on the query results:
verifyListOfExistingPersons(entityManagerFactory);
QuarkusTransaction.requiringNew().run(() -> {
CriteriaBuilder cb = em.getCriteriaBuilder();

CriteriaQuery<Person> cq = cb.createQuery(Person.class);
Root<Person> from = cq.from(Person.class);
cq.select(from).orderBy(cb.asc(from.get("name")));
TypedQuery<Person> q = em.createQuery(cq);
List<Person> allpersons = q.getResultList();
if (allpersons.size() != 3) {
throw new RuntimeException("Incorrect number of results");
}
if (!allpersons.get(0).getName().equals("Gizmo")) {
throw new RuntimeException("Incorrect order of results");
}
StringBuilder sb = new StringBuilder("list of stored Person names:\n\t");
for (Person p : allpersons) {
p.describeFully(sb);
}
sb.append("\nList complete.\n");
System.out.print(sb);
});

//Try a JPA named query:
verifyJPANamedQuery(entityManagerFactory);

verifyHqlFetch(entityManagerFactory);

deleteAllPerson(entityManagerFactory);

return "OK";
}

private static void verifyHqlFetch(EntityManagerFactory emf) {
try (EntityManager em = emf.createEntityManager()) {
EntityTransaction transaction = em.getTransaction();
try {
transaction.begin();

em.createQuery("from Person p left join fetch p.address a").getResultList();

transaction.commit();
} catch (Exception e) {
if (transaction.isActive()) {
transaction.rollback();
}
throw e;
QuarkusTransaction.requiringNew().run(() -> {
TypedQuery<Person> typedQuery = em.createNamedQuery(
"get_person_by_name", Person.class);
typedQuery.setParameter("name", "Quarkus");
final Person singleResult = typedQuery.getSingleResult();

if (!singleResult.getName().equals("Quarkus")) {
throw new RuntimeException("Wrong result from named JPA query");
}
}
}
});

private static void verifyJPANamedQuery(final EntityManagerFactory emf) {
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin();
TypedQuery<Person> typedQuery = em.createNamedQuery(
"get_person_by_name", Person.class);
typedQuery.setParameter("name", "Quarkus");
final Person singleResult = typedQuery.getSingleResult();

if (!singleResult.getName().equals("Quarkus")) {
throw new RuntimeException("Wrong result from named JPA query");
}

transaction.commit();
em.close();
}
//Check that HQL fetch does not fail
QuarkusTransaction.requiringNew()
.run(() -> em.createQuery("from Person p left join fetch p.address a").getResultList());

private static void verifyListOfExistingPersons(final EntityManagerFactory emf) {
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin();
listExistingPersons(em);
transaction.commit();
em.close();
}

private static void storeTestPersons(final EntityManagerFactory emf) {
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin();
persistNewPerson(em, "Gizmo");
persistNewPerson(em, "Quarkus");
persistNewPerson(em, "Hibernate ORM");
transaction.commit();
em.close();
}
cleanUpData();

private static void deleteAllPerson(final EntityManagerFactory emf) {
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin();
em.createNativeQuery("Delete from Person").executeUpdate();
transaction.commit();
em.close();
return "OK";
}

private static void listExistingPersons(EntityManager em) {
CriteriaBuilder cb = em.getCriteriaBuilder();

CriteriaQuery<Person> cq = cb.createQuery(Person.class);
Root<Person> from = cq.from(Person.class);
cq.select(from).orderBy(cb.asc(from.get("name")));
TypedQuery<Person> q = em.createQuery(cq);
List<Person> allpersons = q.getResultList();
if (allpersons.size() != 3) {
throw new RuntimeException("Incorrect number of results");
}
if (!allpersons.get(0).getName().equals("Gizmo")) {
throw new RuntimeException("Incorrect order of results");
}
StringBuilder sb = new StringBuilder("list of stored Person names:\n\t");
for (Person p : allpersons) {
p.describeFully(sb);
}
sb.append("\nList complete.\n");
System.out.print(sb);
private void cleanUpData() {
QuarkusTransaction.requiringNew()
.run(() -> em.createNativeQuery("Delete from Person").executeUpdate());
}

private static void persistNewPerson(EntityManager entityManager, String name) {
private void persistNewPerson(String name) {
Person person = new Person();
person.setName(name);
person.setAddress(new SequencedAddress("Street " + randomName()));
entityManager.persist(person);
em.persist(person);
}

private static String randomName() {
Expand Down
Loading

0 comments on commit 861e286

Please sign in to comment.