diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirSystemDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirSystemDao.java index fa473fb6a3e..1f697f28ecb 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirSystemDao.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirSystemDao.java @@ -177,6 +177,18 @@ public abstract class BaseHapiFhirSystemDao extends B return myTransactionProcessor.transaction(theRequestDetails, theRequest, true); } + /** + * Prefetch entities into the Hibernate session. + * + * When processing several resources (e.g. transaction bundle, $reindex chunk, etc.) + * it would be slow to fetch each piece of a resource (e.g. all token index rows) + * one resource at a time. + * Instead, we fetch all the linked resources for the entire batch here so they are present in the Hibernate Session. + * + * @param theResolvedIds + * @param thePreFetchIndexes Should resource indexes be loaded + * @param

+ */ @Override public

void preFetchResources( List

theResolvedIds, boolean thePreFetchIndexes) { @@ -199,24 +211,7 @@ public abstract class BaseHapiFhirSystemDao extends B if (ids.size() >= 2) { List loadedResourceTableEntries = new ArrayList<>(); - new QueryChunker().chunk(ids, nextChunk -> { - // List allById = myResourceTableDao.findAllById(nextChunk); - Query query = myEntityManager.createQuery("select r, h FROM ResourceTable r " - + " LEFT JOIN fetch ResourceHistoryTable h on r.myVersion = h.myResourceVersion and r.id = h.myResourceId" - + " left join fetch h.myProvenance" - + " WHERE r.myId IN ( :IDS )"); - query.setParameter("IDS", ids); - - @SuppressWarnings("unchecked") - List allById = query.getResultList(); - - for (Object[] nextPair : allById) { - ResourceTable r = (ResourceTable) nextPair[0]; - ResourceHistoryTable h = (ResourceHistoryTable) nextPair[1]; - r.setCurrentVersionEntity(h); - loadedResourceTableEntries.add(r); - } - }); + prefetchResourceTableHistoryAndProvenance(ids, loadedResourceTableEntries); List entityIds; @@ -309,6 +304,30 @@ public abstract class BaseHapiFhirSystemDao extends B }); } + private void prefetchResourceTableHistoryAndProvenance( + List ids, List loadedResourceTableEntries) { + new QueryChunker().chunk(ids, nextChunk -> { + Query query = myEntityManager.createQuery("select r, h " + + " FROM ResourceTable r " + + " LEFT JOIN fetch ResourceHistoryTable h " + + " on r.myVersion = h.myResourceVersion and r.id = h.myResourceId " + + " left join fetch h.myProvenance " + + " WHERE r.myId IN ( :IDS ) "); + query.setParameter("IDS", ids); + + @SuppressWarnings("unchecked") + List allById = query.getResultList(); + + for (Object[] nextPair : allById) { + ResourceTable r = (ResourceTable) nextPair[0]; + ResourceHistoryTable h = (ResourceHistoryTable) nextPair[1]; + // history is a big weird - we hold it in a transient field because we also hold the new version. + r.setCurrentVersionEntity(h); + loadedResourceTableEntries.add(r); + } + }); + } + private void preFetchIndexes( List theIds, String typeDesc,