Use detaching queries for all criteria queries (#1192)

* Make all criteria queries use jpaTm().query()

This causes all criteria queries to detach-on-load.

* Detach results of criteria queries

Wrap the criteria queries in DetachingTypedQuery now that the latter is
merged.
This commit is contained in:
Michael Muller 2021-06-04 14:37:53 -04:00 committed by GitHub
parent 0881a17dca
commit 1aa99bb409
8 changed files with 50 additions and 25 deletions

View file

@ -228,8 +228,7 @@ public abstract class ForeignKeyIndex<E extends EppResource> extends BackupGroup
tm().transact( tm().transact(
() -> () ->
jpaTm() jpaTm()
.getEntityManager() .query(
.createQuery(
CriteriaQueryBuilder.create(clazz) CriteriaQueryBuilder.create(clazz)
.whereFieldIsIn(property, foreignKeys) .whereFieldIsIn(property, foreignKeys)
.build()) .build())

View file

@ -164,8 +164,7 @@ public class HistoryEntryDao {
private static <T extends HistoryEntry> Stream<T> loadHistoryObjectFromSqlByRegistrars( private static <T extends HistoryEntry> Stream<T> loadHistoryObjectFromSqlByRegistrars(
Class<T> historyClass, ImmutableCollection<String> registrarIds) { Class<T> historyClass, ImmutableCollection<String> registrarIds) {
return jpaTm() return jpaTm()
.getEntityManager() .query(
.createQuery(
CriteriaQueryBuilder.create(historyClass) CriteriaQueryBuilder.create(historyClass)
.whereFieldIsIn("clientId", registrarIds) .whereFieldIsIn("clientId", registrarIds)
.build()) .build())
@ -189,7 +188,7 @@ public class HistoryEntryDao {
return ImmutableList.sortedCopyOf( return ImmutableList.sortedCopyOf(
Comparator.comparing(HistoryEntry::getModificationTime), Comparator.comparing(HistoryEntry::getModificationTime),
jpaTm().getEntityManager().createQuery(criteriaQuery).getResultList()); jpaTm().query(criteriaQuery).getResultList());
} }
private static Class<? extends HistoryEntry> getHistoryClassFromParent( private static Class<? extends HistoryEntry> getHistoryClassFromParent(
@ -216,8 +215,7 @@ public class HistoryEntryDao {
Class<T> historyClass, DateTime afterTime, DateTime beforeTime) { Class<T> historyClass, DateTime afterTime, DateTime beforeTime) {
CriteriaBuilder criteriaBuilder = jpaTm().getEntityManager().getCriteriaBuilder(); CriteriaBuilder criteriaBuilder = jpaTm().getEntityManager().getCriteriaBuilder();
return jpaTm() return jpaTm()
.getEntityManager() .query(
.createQuery(
CriteriaQueryBuilder.create(historyClass) CriteriaQueryBuilder.create(historyClass)
.where("modificationTime", criteriaBuilder::greaterThanOrEqualTo, afterTime) .where("modificationTime", criteriaBuilder::greaterThanOrEqualTo, afterTime)
.where("modificationTime", criteriaBuilder::lessThanOrEqualTo, beforeTime) .where("modificationTime", criteriaBuilder::lessThanOrEqualTo, beforeTime)

View file

@ -19,6 +19,7 @@ import java.util.function.Supplier;
import javax.persistence.EntityManager; import javax.persistence.EntityManager;
import javax.persistence.Query; import javax.persistence.Query;
import javax.persistence.TypedQuery; import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaQuery;
/** Sub-interface of {@link TransactionManager} which defines JPA related methods. */ /** Sub-interface of {@link TransactionManager} which defines JPA related methods. */
public interface JpaTransactionManager extends TransactionManager { public interface JpaTransactionManager extends TransactionManager {
@ -34,6 +35,9 @@ public interface JpaTransactionManager extends TransactionManager {
*/ */
<T> TypedQuery<T> query(String sqlString, Class<T> resultClass); <T> TypedQuery<T> query(String sqlString, Class<T> resultClass);
/** Creates a JPA SQU query for the given criteria query. */
<T> TypedQuery<T> query(CriteriaQuery<T> criteriaQuery);
/** /**
* Creates a JPA SQL query for the given query string. * Creates a JPA SQL query for the given query string.
* *

View file

@ -69,6 +69,7 @@ import javax.persistence.PersistenceException;
import javax.persistence.Query; import javax.persistence.Query;
import javax.persistence.TemporalType; import javax.persistence.TemporalType;
import javax.persistence.TypedQuery; import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.metamodel.EntityType; import javax.persistence.metamodel.EntityType;
import javax.persistence.metamodel.SingularAttribute; import javax.persistence.metamodel.SingularAttribute;
import org.joda.time.DateTime; import org.joda.time.DateTime;
@ -127,6 +128,11 @@ public class JpaTransactionManagerImpl implements JpaTransactionManager {
return new DetachingTypedQuery(getEntityManager().createQuery(sqlString, resultClass)); return new DetachingTypedQuery(getEntityManager().createQuery(sqlString, resultClass));
} }
@Override
public <T> TypedQuery<T> query(CriteriaQuery<T> criteriaQuery) {
return new DetachingTypedQuery(getEntityManager().createQuery(criteriaQuery));
}
@Override @Override
public Query query(String sqlString) { public Query query(String sqlString) {
return getEntityManager().createQuery(sqlString); return getEntityManager().createQuery(sqlString);

View file

@ -589,8 +589,7 @@ public class RdapDomainSearchAction extends RdapSearchActionBase {
cursorString.get()); cursorString.get());
} }
jpaTm() jpaTm()
.getEntityManager() .query(queryBuilder.build())
.createQuery(queryBuilder.build())
.getResultStream() .getResultStream()
.filter(this::isAuthorized) .filter(this::isAuthorized)
.forEach( .forEach(

View file

@ -202,11 +202,7 @@ public abstract class RdapSearchActionBase extends RdapActionBase {
desiredRegistrar.get()); desiredRegistrar.get());
} }
List<T> queryResult = List<T> queryResult =
jpaTm() jpaTm().query(builder.build()).setMaxResults(querySizeLimit).getResultList();
.getEntityManager()
.createQuery(builder.build())
.setMaxResults(querySizeLimit)
.getResultList();
if (checkForVisibility) { if (checkForVisibility) {
return filterResourcesByVisibility(queryResult, querySizeLimit); return filterResourcesByVisibility(queryResult, querySizeLimit);
} else { } else {

View file

@ -59,8 +59,7 @@ class CriteriaQueryBuilderTest {
.transact( .transact(
() -> () ->
jpaTm() jpaTm()
.getEntityManager() .query(
.createQuery(
CriteriaQueryBuilder.create(CriteriaQueryBuilderTestEntity.class) CriteriaQueryBuilder.create(CriteriaQueryBuilderTestEntity.class)
.build()) .build())
.getResultList())) .getResultList()))
@ -77,10 +76,11 @@ class CriteriaQueryBuilderTest {
CriteriaQuery<CriteriaQueryBuilderTestEntity> query = CriteriaQuery<CriteriaQueryBuilderTestEntity> query =
CriteriaQueryBuilder.create(CriteriaQueryBuilderTestEntity.class) CriteriaQueryBuilder.create(CriteriaQueryBuilderTestEntity.class)
.where( .where(
"data", jpaTm().getEntityManager().getCriteriaBuilder()::equal, "data",
jpaTm().getEntityManager().getCriteriaBuilder()::equal,
"zztz") "zztz")
.build(); .build();
return jpaTm().getEntityManager().createQuery(query).getResultList(); return jpaTm().query(query).getResultList();
}); });
assertThat(result).containsExactly(entity2); assertThat(result).containsExactly(entity2);
} }
@ -96,7 +96,7 @@ class CriteriaQueryBuilderTest {
.where( .where(
"data", jpaTm().getEntityManager().getCriteriaBuilder()::like, "a%") "data", jpaTm().getEntityManager().getCriteriaBuilder()::like, "a%")
.build(); .build();
return jpaTm().getEntityManager().createQuery(query).getResultList(); return jpaTm().query(query).getResultList();
}); });
assertThat(result).containsExactly(entity3); assertThat(result).containsExactly(entity3);
} }
@ -112,7 +112,7 @@ class CriteriaQueryBuilderTest {
.where( .where(
"data", jpaTm().getEntityManager().getCriteriaBuilder()::like, "%a%") "data", jpaTm().getEntityManager().getCriteriaBuilder()::like, "%a%")
.build(); .build();
return jpaTm().getEntityManager().createQuery(query).getResultList(); return jpaTm().query(query).getResultList();
}); });
assertThat(result).containsExactly(entity1, entity3).inOrder(); assertThat(result).containsExactly(entity1, entity3).inOrder();
} }
@ -132,7 +132,7 @@ class CriteriaQueryBuilderTest {
.where( .where(
"data", jpaTm().getEntityManager().getCriteriaBuilder()::like, "%t%") "data", jpaTm().getEntityManager().getCriteriaBuilder()::like, "%t%")
.build(); .build();
return jpaTm().getEntityManager().createQuery(query).getResultList(); return jpaTm().query(query).getResultList();
}); });
assertThat(result).containsExactly(entity1); assertThat(result).containsExactly(entity1);
} }
@ -147,7 +147,7 @@ class CriteriaQueryBuilderTest {
CriteriaQueryBuilder.create(CriteriaQueryBuilderTestEntity.class) CriteriaQueryBuilder.create(CriteriaQueryBuilderTestEntity.class)
.whereFieldIsIn("data", ImmutableList.of("aaa", "bbb")) .whereFieldIsIn("data", ImmutableList.of("aaa", "bbb"))
.build(); .build();
return jpaTm().getEntityManager().createQuery(query).getResultList(); return jpaTm().query(query).getResultList();
}); });
assertThat(result).containsExactly(entity3).inOrder(); assertThat(result).containsExactly(entity3).inOrder();
} }
@ -162,7 +162,7 @@ class CriteriaQueryBuilderTest {
CriteriaQueryBuilder.create(CriteriaQueryBuilderTestEntity.class) CriteriaQueryBuilder.create(CriteriaQueryBuilderTestEntity.class)
.whereFieldIsIn("data", ImmutableList.of("aaa", "bbb", "data")) .whereFieldIsIn("data", ImmutableList.of("aaa", "bbb", "data"))
.build(); .build();
return jpaTm().getEntityManager().createQuery(query).getResultList(); return jpaTm().query(query).getResultList();
}); });
assertThat(result).containsExactly(entity1, entity3).inOrder(); assertThat(result).containsExactly(entity1, entity3).inOrder();
} }
@ -179,7 +179,7 @@ class CriteriaQueryBuilderTest {
.where( .where(
"data", jpaTm().getEntityManager().getCriteriaBuilder()::like, "%a%") "data", jpaTm().getEntityManager().getCriteriaBuilder()::like, "%a%")
.build(); .build();
return jpaTm().getEntityManager().createQuery(query).getResultList(); return jpaTm().query(query).getResultList();
}); });
assertThat(result).containsExactly(entity3, entity1).inOrder(); assertThat(result).containsExactly(entity3, entity1).inOrder();
} }
@ -194,7 +194,7 @@ class CriteriaQueryBuilderTest {
CriteriaQueryBuilder.create(CriteriaQueryBuilderTestEntity.class) CriteriaQueryBuilder.create(CriteriaQueryBuilderTestEntity.class)
.orderByDesc("data") .orderByDesc("data")
.build(); .build();
return jpaTm().getEntityManager().createQuery(query).getResultList(); return jpaTm().query(query).getResultList();
}); });
assertThat(result).containsExactly(entity2, entity1, entity3).inOrder(); assertThat(result).containsExactly(entity2, entity1, entity3).inOrder();
} }

View file

@ -585,6 +585,29 @@ class JpaTransactionManagerImplTest {
.contains("Inserted/updated object reloaded: "); .contains("Inserted/updated object reloaded: ");
} }
@Test
void cqQuery_detaches() {
jpaTm().transact(() -> jpaTm().insertAll(moreEntities));
jpaTm()
.transact(
() ->
assertThat(
jpaTm()
.getEntityManager()
.contains(
jpaTm()
.query(
CriteriaQueryBuilder.create(TestEntity.class)
.where(
"name",
jpaTm().getEntityManager().getCriteriaBuilder()
::equal,
"entity1")
.build())
.getSingleResult()))
.isFalse());
}
@Test @Test
void loadAfterPut_fails() { void loadAfterPut_fails() {
assertThat( assertThat(