mirror of
https://github.com/hapifhir/hapi-fhir.git
synced 2025-02-18 10:55:22 +00:00
Add non-standard __pid SP for breaking ties cheaply during sorts. (#5428)
Add a non-standard __pid SP.
This commit is contained in:
parent
33ca4e9b99
commit
2ef2924b86
@ -199,6 +199,8 @@ public class Constants {
|
|||||||
public static final String PARAM_PRETTY_VALUE_FALSE = "false";
|
public static final String PARAM_PRETTY_VALUE_FALSE = "false";
|
||||||
public static final String PARAM_PRETTY_VALUE_TRUE = "true";
|
public static final String PARAM_PRETTY_VALUE_TRUE = "true";
|
||||||
public static final String PARAM_PROFILE = "_profile";
|
public static final String PARAM_PROFILE = "_profile";
|
||||||
|
public static final String PARAM__PID = "__pid";
|
||||||
|
|
||||||
public static final String PARAM_QUERY = "_query";
|
public static final String PARAM_QUERY = "_query";
|
||||||
public static final String PARAM_RESPONSE_URL = "response-url"; // Used in messaging
|
public static final String PARAM_RESPONSE_URL = "response-url"; // Used in messaging
|
||||||
public static final String PARAM_REVINCLUDE = "_revinclude";
|
public static final String PARAM_REVINCLUDE = "_revinclude";
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
type: add
|
||||||
|
issue: 5428
|
||||||
|
title: "Add support for non-standard __pid SearchParameter to the the JPA engine.
|
||||||
|
This new SP provides an efficient tie-breaking sort key."
|
@ -22,6 +22,10 @@ Searching on Location.Position using `near` currently uses a box search, not a r
|
|||||||
|
|
||||||
The special `_filter` is only partially implemented.
|
The special `_filter` is only partially implemented.
|
||||||
|
|
||||||
|
### __pid
|
||||||
|
|
||||||
|
The JPA server implements a non-standard special `__pid` which matches/sorts on the raw internal database id.
|
||||||
|
This sort is useful for imposing tie-breaking sort order in an efficient way.
|
||||||
|
|
||||||
<a name="uplifted-refchains"/>
|
<a name="uplifted-refchains"/>
|
||||||
|
|
||||||
|
@ -285,6 +285,12 @@ public class QueryStack {
|
|||||||
mySqlBuilder.addSortString(resourceTablePredicateBuilder.getColumnFhirId(), theAscending, myUseAggregate);
|
mySqlBuilder.addSortString(resourceTablePredicateBuilder.getColumnFhirId(), theAscending, myUseAggregate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Sort on RES_ID -- used to break ties for reliable sort */
|
||||||
|
public void addSortOnResourcePID(boolean theAscending) {
|
||||||
|
BaseJoiningPredicateBuilder predicateBuilder = mySqlBuilder.getOrCreateFirstPredicateBuilder();
|
||||||
|
mySqlBuilder.addSortString(predicateBuilder.getResourceIdColumn(), theAscending);
|
||||||
|
}
|
||||||
|
|
||||||
public void addSortOnResourceLink(
|
public void addSortOnResourceLink(
|
||||||
String theResourceName,
|
String theResourceName,
|
||||||
String theReferenceTargetType,
|
String theReferenceTargetType,
|
||||||
@ -2287,6 +2293,10 @@ public class QueryStack {
|
|||||||
null,
|
null,
|
||||||
theSearchForIdsParams.myRequestPartitionId);
|
theSearchForIdsParams.myRequestPartitionId);
|
||||||
|
|
||||||
|
case Constants.PARAM__PID:
|
||||||
|
return createPredicateResourcePID(
|
||||||
|
theSearchForIdsParams.mySourceJoinColumn, theSearchForIdsParams.myAndOrParams);
|
||||||
|
|
||||||
case PARAM_HAS:
|
case PARAM_HAS:
|
||||||
return createPredicateHas(
|
return createPredicateHas(
|
||||||
theSearchForIdsParams.mySourceJoinColumn,
|
theSearchForIdsParams.mySourceJoinColumn,
|
||||||
@ -2337,6 +2347,36 @@ public class QueryStack {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Raw match on RES_ID
|
||||||
|
*/
|
||||||
|
private Condition createPredicateResourcePID(
|
||||||
|
DbColumn theSourceJoinColumn, List<List<IQueryParameterType>> theAndOrParams) {
|
||||||
|
|
||||||
|
DbColumn pidColumn = theSourceJoinColumn;
|
||||||
|
|
||||||
|
if (pidColumn == null) {
|
||||||
|
BaseJoiningPredicateBuilder predicateBuilder = mySqlBuilder.getOrCreateFirstPredicateBuilder();
|
||||||
|
pidColumn = predicateBuilder.getResourceIdColumn();
|
||||||
|
}
|
||||||
|
|
||||||
|
// we don't support any modifiers for now
|
||||||
|
Set<Long> pids = theAndOrParams.stream()
|
||||||
|
.map(orList -> orList.stream()
|
||||||
|
.map(v -> v.getValueAsQueryToken(myFhirContext))
|
||||||
|
.map(Long::valueOf)
|
||||||
|
.collect(Collectors.toSet()))
|
||||||
|
.reduce(Sets::intersection)
|
||||||
|
.orElse(Set.of());
|
||||||
|
|
||||||
|
if (pids.isEmpty()) {
|
||||||
|
mySqlBuilder.setMatchNothing();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return toEqualToOrInPredicate(pidColumn, mySqlBuilder.generatePlaceholders(pids));
|
||||||
|
}
|
||||||
|
|
||||||
private Condition createReverseSearchPredicateLastUpdated(
|
private Condition createReverseSearchPredicateLastUpdated(
|
||||||
List<List<IQueryParameterType>> theAndOrParams, DbColumn theSourceColumn) {
|
List<List<IQueryParameterType>> theAndOrParams, DbColumn theSourceColumn) {
|
||||||
|
|
||||||
|
@ -838,6 +838,10 @@ public class SearchBuilder implements ISearchBuilder<JpaPid> {
|
|||||||
|
|
||||||
theQueryStack.addSortOnResourceId(ascending);
|
theQueryStack.addSortOnResourceId(ascending);
|
||||||
|
|
||||||
|
} else if (Constants.PARAM__PID.equals(theSort.getParamName())) {
|
||||||
|
|
||||||
|
theQueryStack.addSortOnResourcePID(ascending);
|
||||||
|
|
||||||
} else if (Constants.PARAM_LASTUPDATED.equals(theSort.getParamName())) {
|
} else if (Constants.PARAM_LASTUPDATED.equals(theSort.getParamName())) {
|
||||||
|
|
||||||
theQueryStack.addSortOnLastUpdated(ascending);
|
theQueryStack.addSortOnLastUpdated(ascending);
|
||||||
|
@ -51,6 +51,8 @@ public class ResourceMetaParams {
|
|||||||
Map<String, Class<? extends IQueryParameterAnd<?>>> resourceMetaAndParams = new HashMap<>();
|
Map<String, Class<? extends IQueryParameterAnd<?>>> resourceMetaAndParams = new HashMap<>();
|
||||||
resourceMetaParams.put(IAnyResource.SP_RES_ID, StringParam.class);
|
resourceMetaParams.put(IAnyResource.SP_RES_ID, StringParam.class);
|
||||||
resourceMetaAndParams.put(IAnyResource.SP_RES_ID, StringAndListParam.class);
|
resourceMetaAndParams.put(IAnyResource.SP_RES_ID, StringAndListParam.class);
|
||||||
|
resourceMetaParams.put(Constants.PARAM__PID, TokenParam.class);
|
||||||
|
resourceMetaAndParams.put(Constants.PARAM__PID, TokenAndListParam.class);
|
||||||
resourceMetaParams.put(Constants.PARAM_TAG, TokenParam.class);
|
resourceMetaParams.put(Constants.PARAM_TAG, TokenParam.class);
|
||||||
resourceMetaAndParams.put(Constants.PARAM_TAG, TokenAndListParam.class);
|
resourceMetaAndParams.put(Constants.PARAM_TAG, TokenAndListParam.class);
|
||||||
resourceMetaParams.put(Constants.PARAM_PROFILE, UriParam.class);
|
resourceMetaParams.put(Constants.PARAM_PROFILE, UriParam.class);
|
||||||
|
@ -0,0 +1,150 @@
|
|||||||
|
package ca.uhn.fhir.jpa.dao.r4;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.interceptor.api.Hook;
|
||||||
|
import ca.uhn.fhir.interceptor.api.Pointcut;
|
||||||
|
import ca.uhn.fhir.jpa.dao.TestDaoSearch;
|
||||||
|
import ca.uhn.fhir.jpa.test.BaseJpaTest;
|
||||||
|
import ca.uhn.fhir.jpa.test.config.TestHSearchAddInConfig;
|
||||||
|
import ca.uhn.fhir.jpa.test.config.TestR4Config;
|
||||||
|
import ca.uhn.fhir.jpa.util.SqlQuery;
|
||||||
|
import ca.uhn.fhir.jpa.util.SqlQueryList;
|
||||||
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
|
import ca.uhn.fhir.storage.test.DaoTestDataBuilder;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.test.annotation.DirtiesContext;
|
||||||
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
|
import org.springframework.test.context.TestContext;
|
||||||
|
import org.springframework.test.context.TestExecutionListeners;
|
||||||
|
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||||
|
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
|
||||||
|
import org.springframework.test.context.support.DirtiesContextTestExecutionListener;
|
||||||
|
import org.springframework.transaction.PlatformTransactionManager;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.hamcrest.Matchers.empty;
|
||||||
|
import static org.hamcrest.Matchers.not;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sandbox for implementing queries.
|
||||||
|
* This will NOT run during the build - use this class as a convenient
|
||||||
|
* place to explore, debug, profile, and optimize.
|
||||||
|
*/
|
||||||
|
@ExtendWith(SpringExtension.class)
|
||||||
|
@ContextConfiguration(classes = {
|
||||||
|
TestR4Config.class,
|
||||||
|
TestHSearchAddInConfig.NoFT.class,
|
||||||
|
DaoTestDataBuilder.Config.class,
|
||||||
|
TestDaoSearch.Config.class
|
||||||
|
})
|
||||||
|
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
|
||||||
|
@TestExecutionListeners(listeners = {
|
||||||
|
DependencyInjectionTestExecutionListener.class
|
||||||
|
, FhirResourceDaoR4QuerySandbox.TestDirtiesContextTestExecutionListener.class
|
||||||
|
})
|
||||||
|
public class FhirResourceDaoR4QuerySandbox extends BaseJpaTest {
|
||||||
|
private static final Logger ourLog = LoggerFactory.getLogger(FhirResourceDaoR4QuerySandbox.class);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
PlatformTransactionManager myTxManager;
|
||||||
|
@Autowired
|
||||||
|
FhirContext myFhirCtx;
|
||||||
|
@RegisterExtension
|
||||||
|
@Autowired
|
||||||
|
DaoTestDataBuilder myDataBuilder;
|
||||||
|
@Autowired
|
||||||
|
TestDaoSearch myTestDaoSearch;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected PlatformTransactionManager getTxManager() {
|
||||||
|
return myTxManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected FhirContext getFhirContext() {
|
||||||
|
return myFhirCtx;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> myCapturedQueries = new ArrayList<>();
|
||||||
|
@BeforeEach
|
||||||
|
void registerLoggingInterceptor() {
|
||||||
|
registerInterceptor(new Object(){
|
||||||
|
@Hook(Pointcut.JPA_PERFTRACE_RAW_SQL)
|
||||||
|
public void captureSql(RequestDetails theRequestDetails, SqlQueryList theQueries) {
|
||||||
|
for (SqlQuery next : theQueries) {
|
||||||
|
String output = next.getSql(true, true, true);
|
||||||
|
ourLog.info("Query: {}", output);
|
||||||
|
myCapturedQueries.add(output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSearches_logQueries() {
|
||||||
|
myDataBuilder.createPatient();
|
||||||
|
|
||||||
|
myTestDaoSearch.searchForIds("Patient?name=smith");
|
||||||
|
|
||||||
|
assertThat(myCapturedQueries, not(empty()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testQueryByPid() {
|
||||||
|
|
||||||
|
// sentinel for over-match
|
||||||
|
myDataBuilder.createPatient();
|
||||||
|
|
||||||
|
String id = myDataBuilder.createPatient(
|
||||||
|
myDataBuilder.withBirthdate("1971-01-01"),
|
||||||
|
myDataBuilder.withActiveTrue(),
|
||||||
|
myDataBuilder.withFamily("Smith")).getIdPart();
|
||||||
|
|
||||||
|
myTestDaoSearch.assertSearchFindsOnly("search by server assigned id", "Patient?__pid=" + id, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testQueryByPid_withOtherSPAvoidsResourceTable() {
|
||||||
|
// sentinel for over-match
|
||||||
|
myDataBuilder.createPatient();
|
||||||
|
|
||||||
|
String id = myDataBuilder.createPatient(
|
||||||
|
myDataBuilder.withBirthdate("1971-01-01"),
|
||||||
|
myDataBuilder.withActiveTrue(),
|
||||||
|
myDataBuilder.withFamily("Smith")).getIdPart();
|
||||||
|
|
||||||
|
myTestDaoSearch.assertSearchFindsOnly("search by server assigned id", "Patient?name=smith&__pid=" + id, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testSortByPid() {
|
||||||
|
|
||||||
|
String id1 = myDataBuilder.createPatient(myDataBuilder.withFamily("Smithy")).getIdPart();
|
||||||
|
String id2 = myDataBuilder.createPatient(myDataBuilder.withFamily("Smithwick")).getIdPart();
|
||||||
|
String id3 = myDataBuilder.createPatient(myDataBuilder.withFamily("Smith")).getIdPart();
|
||||||
|
|
||||||
|
myTestDaoSearch.assertSearchFindsInOrder("sort by server assigned id", "Patient?family=smith&_sort=__pid", id1,id2,id3);
|
||||||
|
myTestDaoSearch.assertSearchFindsInOrder("reverse sort by server assigned id", "Patient?family=smith&_sort=-__pid", id3,id2,id1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class TestDirtiesContextTestExecutionListener extends DirtiesContextTestExecutionListener {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void beforeOrAfterTestClass(TestContext testContext, DirtiesContext.ClassMode requiredClassMode) throws Exception {
|
||||||
|
if (!testContext.getTestClass().getName().contains("$")) {
|
||||||
|
super.beforeOrAfterTestClass(testContext, requiredClassMode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -4,10 +4,10 @@ import ca.uhn.fhir.context.FhirContext;
|
|||||||
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
|
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
|
||||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
|
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
|
||||||
import ca.uhn.fhir.jpa.dao.TestDaoSearch;
|
import ca.uhn.fhir.jpa.dao.TestDaoSearch;
|
||||||
|
import ca.uhn.fhir.jpa.search.BaseSourceSearchParameterTestCases;
|
||||||
import ca.uhn.fhir.jpa.search.CompositeSearchParameterTestCases;
|
import ca.uhn.fhir.jpa.search.CompositeSearchParameterTestCases;
|
||||||
import ca.uhn.fhir.jpa.search.IIdSearchTestTemplate;
|
import ca.uhn.fhir.jpa.search.IIdSearchTestTemplate;
|
||||||
import ca.uhn.fhir.jpa.search.QuantitySearchParameterTestCases;
|
import ca.uhn.fhir.jpa.search.QuantitySearchParameterTestCases;
|
||||||
import ca.uhn.fhir.jpa.search.BaseSourceSearchParameterTestCases;
|
|
||||||
import ca.uhn.fhir.jpa.searchparam.MatchUrlService;
|
import ca.uhn.fhir.jpa.searchparam.MatchUrlService;
|
||||||
import ca.uhn.fhir.jpa.test.BaseJpaTest;
|
import ca.uhn.fhir.jpa.test.BaseJpaTest;
|
||||||
import ca.uhn.fhir.jpa.test.config.TestHSearchAddInConfig;
|
import ca.uhn.fhir.jpa.test.config.TestHSearchAddInConfig;
|
||||||
@ -38,9 +38,14 @@ import static org.hamcrest.MatcherAssert.assertThat;
|
|||||||
import static org.hamcrest.Matchers.contains;
|
import static org.hamcrest.Matchers.contains;
|
||||||
import static org.hamcrest.Matchers.equalTo;
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
import static org.hamcrest.Matchers.hasItem;
|
import static org.hamcrest.Matchers.hasItem;
|
||||||
import static org.hamcrest.Matchers.hasItems;
|
|
||||||
import static org.hamcrest.Matchers.not;
|
import static org.hamcrest.Matchers.not;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify that our query behaviour matches the spec.
|
||||||
|
* Note: we do not extend BaseJpaR4Test here.
|
||||||
|
* That does a full purge in @AfterEach which is a bit slow.
|
||||||
|
* Instead, this test tracks all created resources in DaoTestDataBuilder, and deletes them in teardown.
|
||||||
|
*/
|
||||||
@ExtendWith(SpringExtension.class)
|
@ExtendWith(SpringExtension.class)
|
||||||
@ContextConfiguration(classes = {
|
@ContextConfiguration(classes = {
|
||||||
TestR4Config.class,
|
TestR4Config.class,
|
||||||
@ -499,6 +504,32 @@ public class FhirResourceDaoR4StandardQueriesNoFTTest extends BaseJpaTest {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testQueryByPid() {
|
||||||
|
|
||||||
|
// sentinel for over-match
|
||||||
|
myDataBuilder.createPatient();
|
||||||
|
|
||||||
|
String id = myDataBuilder.createPatient(
|
||||||
|
myDataBuilder.withBirthdate("1971-01-01"),
|
||||||
|
myDataBuilder.withActiveTrue(),
|
||||||
|
myDataBuilder.withFamily("Smith")).getIdPart();
|
||||||
|
|
||||||
|
myTestDaoSearch.assertSearchFindsOnly("search by server assigned id", "Patient?__pid=" + id, id);
|
||||||
|
myTestDaoSearch.assertSearchFindsOnly("search by server assigned id", "Patient?family=smith&__pid=" + id, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testSortByPid() {
|
||||||
|
|
||||||
|
String id1 = myDataBuilder.createPatient(myDataBuilder.withFamily("Smithy")).getIdPart();
|
||||||
|
String id2 = myDataBuilder.createPatient(myDataBuilder.withFamily("Smithwick")).getIdPart();
|
||||||
|
String id3 = myDataBuilder.createPatient(myDataBuilder.withFamily("Smith")).getIdPart();
|
||||||
|
|
||||||
|
myTestDaoSearch.assertSearchFindsInOrder("sort by server assigned id", "Patient?family=smith&_sort=__pid", id1,id2,id3);
|
||||||
|
myTestDaoSearch.assertSearchFindsInOrder("reverse sort by server assigned id", "Patient?family=smith&_sort=-__pid", id3,id2,id1);
|
||||||
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
public class IdSearch implements IIdSearchTestTemplate {
|
public class IdSearch implements IIdSearchTestTemplate {
|
||||||
@Override
|
@Override
|
||||||
|
@ -48,6 +48,7 @@ import javax.annotation.Nonnull;
|
|||||||
|
|
||||||
import static org.apache.commons.lang3.ArrayUtils.EMPTY_STRING_ARRAY;
|
import static org.apache.commons.lang3.ArrayUtils.EMPTY_STRING_ARRAY;
|
||||||
import static org.hamcrest.Matchers.contains;
|
import static org.hamcrest.Matchers.contains;
|
||||||
|
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||||
import static org.hamcrest.Matchers.everyItem;
|
import static org.hamcrest.Matchers.everyItem;
|
||||||
import static org.hamcrest.Matchers.hasItems;
|
import static org.hamcrest.Matchers.hasItems;
|
||||||
import static org.hamcrest.Matchers.in;
|
import static org.hamcrest.Matchers.in;
|
||||||
@ -133,6 +134,17 @@ public class TestDaoSearch {
|
|||||||
assertSearchFindsInOrder(theReason, theQueryUrl, theIds.toArray(EMPTY_STRING_ARRAY));
|
assertSearchFindsInOrder(theReason, theQueryUrl, theIds.toArray(EMPTY_STRING_ARRAY));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void assertSearchFindsOnly(String theReason, String theQueryUrl, String... theIds) {
|
||||||
|
assertSearchIdsMatch(theReason, theQueryUrl, containsInAnyOrder(theIds));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void assertSearchIdsMatch(
|
||||||
|
String theReason, String theQueryUrl, Matcher<? super Iterable<String>> theMatchers) {
|
||||||
|
List<String> ids = searchForIds(theQueryUrl);
|
||||||
|
|
||||||
|
MatcherAssert.assertThat(theReason, ids, theMatchers);
|
||||||
|
}
|
||||||
|
|
||||||
public void assertSearchResultIds(String theQueryUrl, String theReason, Matcher<Iterable<String>> matcher) {
|
public void assertSearchResultIds(String theQueryUrl, String theReason, Matcher<Iterable<String>> matcher) {
|
||||||
List<String> ids = searchForIds(theQueryUrl);
|
List<String> ids = searchForIds(theQueryUrl);
|
||||||
|
|
||||||
|
@ -431,6 +431,11 @@ public abstract class BaseJpaTest extends BaseTest {
|
|||||||
return deliveryLatch;
|
return deliveryLatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void registerInterceptor(Object theInterceptor) {
|
||||||
|
myRegisteredInterceptors.add(theInterceptor);
|
||||||
|
myInterceptorRegistry.registerInterceptor(theInterceptor);
|
||||||
|
}
|
||||||
|
|
||||||
protected void purgeHibernateSearch(EntityManager theEntityManager) {
|
protected void purgeHibernateSearch(EntityManager theEntityManager) {
|
||||||
runInTransaction(() -> {
|
runInTransaction(() -> {
|
||||||
if (myFulltestSearchSvc != null && !myFulltestSearchSvc.isDisabled()) {
|
if (myFulltestSearchSvc != null && !myFulltestSearchSvc.isDisabled()) {
|
||||||
|
@ -39,7 +39,8 @@ import org.springframework.context.annotation.Configuration;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements ITestDataBuilder via a live DaoRegistry.
|
* Implements ITestDataBuilder via a live DaoRegistry.
|
||||||
*
|
* Note: this implements {@link AfterEachCallback} and will delete any resources created when registered
|
||||||
|
* via {@link org.junit.jupiter.api.extension.RegisterExtension}.
|
||||||
* Add the inner {@link Config} to your spring context to inject this.
|
* Add the inner {@link Config} to your spring context to inject this.
|
||||||
* For convenience, you can still implement ITestDataBuilder on your test class, and delegate the missing methods to this bean.
|
* For convenience, you can still implement ITestDataBuilder on your test class, and delegate the missing methods to this bean.
|
||||||
*/
|
*/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user