More work on optimizing JPA

This commit is contained in:
jamesagnew 2018-01-08 07:15:58 -05:00
parent 8b38334955
commit 6fc88caa51
21 changed files with 387 additions and 182 deletions

View File

@ -1264,6 +1264,10 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
history = myResourceHistoryTableDao.findForIdAndVersion(theEntity.getId(), theEntity.getVersion());
}
if (history == null) {
return null;
}
byte[] resourceBytes = history.getResource();
ResourceEncodingEnum resourceEncoding = history.getEncoding();
@ -1596,6 +1600,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
theEntity.setParamsUriPopulated(uriParams.isEmpty() == false);
theEntity.setParamsCoords(coordsParams);
theEntity.setParamsCoordsPopulated(coordsParams.isEmpty() == false);
theEntity.setParamsCompositeStringUnique(compositeStringUniques);
theEntity.setParamsCompositeStringUniquePresent(compositeStringUniques.isEmpty() == false);
theEntity.setResourceLinks(links);
theEntity.setHasLinks(links.isEmpty() == false);
@ -1645,6 +1650,18 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
postUpdate(theEntity, (T) theResource);
}
/*
* Create history entry
*/
if (theCreateNewHistoryEntry) {
final ResourceHistoryTable historyEntry = theEntity.toHistory();
historyEntry.setEncoding(changed.getEncoding());
historyEntry.setResource(changed.getResource());
ourLog.info("Saving history entry {}", historyEntry.getIdDt());
myResourceHistoryTableDao.save(historyEntry);
}
/*
* Update the "search param present" table which is used for the
* ?foo:missing=true queries
@ -1671,18 +1688,6 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
mySearchParamPresenceSvc.updatePresence(theEntity, presentSearchParams);
}
/*
* Create history entry
*/
if (theCreateNewHistoryEntry) {
final ResourceHistoryTable historyEntry = theEntity.toHistory();
historyEntry.setEncoding(changed.getEncoding());
historyEntry.setResource(changed.getResource());
ourLog.info("Saving history entry {}", historyEntry.getIdDt());
myResourceHistoryTableDao.save(historyEntry);
}
/*
* Indexing
*/

View File

@ -9,9 +9,9 @@ package ca.uhn.fhir.jpa.dao;
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -51,6 +51,7 @@ import ca.uhn.fhir.util.FhirTerser;
import ca.uhn.fhir.util.ObjectUtil;
import ca.uhn.fhir.util.OperationOutcomeUtil;
import ca.uhn.fhir.util.ResourceReferenceInfo;
import com.google.common.annotations.VisibleForTesting;
import org.apache.commons.lang3.Validate;
import org.hl7.fhir.instance.model.api.*;
import org.springframework.beans.factory.annotation.Autowired;
@ -75,6 +76,7 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends BaseHapiFhirDao<T> implements IFhirResourceDao<T> {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseHapiFhirResourceDao.class);
private static boolean ourDisableIncrementOnUpdateForUnitTest = false;
@Autowired
protected PlatformTransactionManager myPlatformTransactionManager;
@Autowired
@ -84,7 +86,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
@Autowired()
protected ISearchResultDao mySearchResultDao;
@Autowired
private DaoConfig myDaoConfig;
protected DaoConfig myDaoConfig;
@Autowired
private IResourceHistoryTableDao myResourceHistoryTableDao;
@Autowired
@ -92,7 +94,6 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
private String myResourceName;
private Class<T> myResourceType;
private String mySecondaryPrimaryKeyParamName;
@Autowired
private ISearchParamRegistry mySearchParamRegistry;
@ -192,6 +193,25 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
throw new ResourceVersionConflictException("Trying to delete " + theId + " but this is not the current version");
}
// Don't delete again if it's already deleted
if (entity.getDeleted() != null) {
DaoMethodOutcome outcome = new DaoMethodOutcome();
outcome.setEntity(entity);
IIdType id = getContext().getVersion().newIdType();
id.setValue(entity.getIdDt().getValue());
outcome.setId(id);
IBaseOperationOutcome oo = OperationOutcomeUtil.newInstance(getContext());
String message = getContext().getLocalizer().getMessage(BaseHapiFhirResourceDao.class, "successfulDeletes", 1, 0);
String severity = "information";
String code = "informational";
OperationOutcomeUtil.addIssue(getContext(), oo, severity, message, null, code);
outcome.setOperationOutcome(oo);
return outcome;
}
StopWatch w = new StopWatch();
T resourceToDelete = toResource(myResourceType, entity, false);
@ -206,7 +226,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
}
}
validateOkToDelete(theDeleteConflicts, entity);
validateOkToDelete(theDeleteConflicts, entity, false);
preDelete(resourceToDelete, entity);
@ -288,7 +308,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
}
}
validateOkToDelete(deleteConflicts, entity);
validateOkToDelete(deleteConflicts, entity, false);
// Notify interceptors
IdDt idToDelete = entity.getIdDt();
@ -300,7 +320,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
// Perform delete
Date updateTime = new Date();
updateEntity(null, entity, updateTime, updateTime);
resourceToDelete.setId(entity.getIdDt());
resourceToDelete.setId(entity.getIdDt());
// Notify JPA interceptors
if (theRequestDetails != null) {
@ -1222,12 +1242,12 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
// Perform update
ResourceTable savedEntity = updateEntity(theResource, entity, null, thePerformIndexing, thePerformIndexing, new Date(), theForceUpdateVersion, thePerformIndexing);
/*
/*
* If we aren't indexing (meaning we're probably executing a sub-operation within a transaction),
* we'll manually increase the version. This is important because we want the updated version number
* to be reflected in the resource shared with interceptors
*/
if (!thePerformIndexing && !savedEntity.isUnchangedInCurrentOperation()) {
if (!thePerformIndexing && !savedEntity.isUnchangedInCurrentOperation() && !ourDisableIncrementOnUpdateForUnitTest) {
if (resourceId.hasVersionIdPart() == false) {
resourceId = resourceId.withVersion(Long.toString(savedEntity.getVersion()));
}
@ -1259,7 +1279,6 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
return outcome;
}
@Override
public DaoMethodOutcome update(T theResource, String theMatchUrl, boolean thePerformIndexing, RequestDetails theRequestDetails) {
return update(theResource, theMatchUrl, thePerformIndexing, false, theRequestDetails);
@ -1303,7 +1322,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
}
}
protected void validateOkToDelete(List<DeleteConflict> theDeleteConflicts, ResourceTable theEntity) {
protected void validateOkToDelete(List<DeleteConflict> theDeleteConflicts, ResourceTable theEntity, boolean theForValidate) {
TypedQuery<ResourceLink> query = myEntityManager.createQuery("SELECT l FROM ResourceLink l WHERE l.myTargetResourcePid = :target_pid", ResourceLink.class);
query.setParameter("target_pid", theEntity.getId());
query.setMaxResults(1);
@ -1312,7 +1331,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
return;
}
if (myDaoConfig.isEnforceReferentialIntegrityOnDelete() == false) {
if (myDaoConfig.isEnforceReferentialIntegrityOnDelete() == false && !theForValidate) {
ourLog.info("Deleting {} resource dependencies which can no longer be satisfied", resultList.size());
myResourceLinkDao.delete(resultList);
return;
@ -1336,4 +1355,9 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
}
}
@VisibleForTesting
public static void setDisableIncrementOnUpdateForUnitTest(boolean theDisableIncrementOnUpdateForUnitTest) {
ourDisableIncrementOnUpdateForUnitTest = theDisableIncrementOnUpdateForUnitTest;
}
}

View File

@ -80,7 +80,9 @@ public class FhirResourceDaoDstu2<T extends IResource> extends BaseHapiFhirResou
// Validate that there are no resources pointing to the candidate that
// would prevent deletion
List<DeleteConflict> deleteConflicts = new ArrayList<DeleteConflict>();
validateOkToDelete(deleteConflicts, entity);
if (myDaoConfig.isEnforceReferentialIntegrityOnDelete()) {
validateOkToDelete(deleteConflicts, entity, true);
}
validateDeleteConflictsEmptyOrThrowException(deleteConflicts);
OperationOutcome oo = new OperationOutcome();

View File

@ -1587,6 +1587,10 @@ public class SearchBuilder implements ISearchBuilder {
for (ResourceTable next : resultList) {
Class<? extends IBaseResource> resourceType = context.getResourceDefinition(next.getResourceType()).getImplementingClass();
IBaseResource resource = theDao.toResource(resourceType, next, theForHistoryOperation);
if (resource == null) {
ourLog.warn("Unable to find resource {}/{}/_history/{} in database", next.getResourceType(), next.getIdDt().getIdPart(), next.getVersion());
continue;
}
Integer index = position.get(next.getId());
if (index == null) {
ourLog.warn("Got back unexpected resource PID {}", next.getId());

View File

@ -85,7 +85,9 @@ public class FhirResourceDaoDstu3<T extends IAnyResource> extends BaseHapiFhirRe
// Validate that there are no resources pointing to the candidate that
// would prevent deletion
List<DeleteConflict> deleteConflicts = new ArrayList<DeleteConflict>();
validateOkToDelete(deleteConflicts, entity);
if (myDaoConfig.isEnforceReferentialIntegrityOnDelete()) {
validateOkToDelete(deleteConflicts, entity, true);
}
validateDeleteConflictsEmptyOrThrowException(deleteConflicts);
OperationOutcome oo = new OperationOutcome();

View File

@ -85,7 +85,9 @@ public class FhirResourceDaoR4<T extends IAnyResource> extends BaseHapiFhirResou
// Validate that there are no resources pointing to the candidate that
// would prevent deletion
List<DeleteConflict> deleteConflicts = new ArrayList<DeleteConflict>();
validateOkToDelete(deleteConflicts, entity);
if (myDaoConfig.isEnforceReferentialIntegrityOnDelete()) {
validateOkToDelete(deleteConflicts, entity, true);
}
validateDeleteConflictsEmptyOrThrowException(deleteConflicts);
OperationOutcome oo = new OperationOutcome();

View File

@ -22,6 +22,7 @@ import org.hl7.fhir.dstu3.model.Resource;
import org.hl7.fhir.instance.model.api.IBaseBundle;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.mockito.Mockito;
@ -57,6 +58,11 @@ public abstract class BaseJpaTest {
when(mySrd.getUserData()).thenReturn(new HashMap<>());
}
@After
public final void afterPerformCleanup() {
BaseHapiFhirResourceDao.setDisableIncrementOnUpdateForUnitTest(false);
}
protected abstract FhirContext getContext();
/**

View File

@ -8,10 +8,13 @@ import java.util.List;
import javax.servlet.http.HttpServletRequest;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.entity.ResourceTable;
import org.hl7.fhir.instance.model.api.IIdType;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.Test;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
@ -24,6 +27,7 @@ import ca.uhn.fhir.model.primitive.StringDt;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.param.*;
import ca.uhn.fhir.util.TestUtil;
import org.springframework.transaction.support.TransactionTemplate;
public class FhirResourceDaoDstu2SearchFtTest extends BaseJpaDstu2Test {
@ -392,13 +396,14 @@ public class FhirResourceDaoDstu2SearchFtTest extends BaseJpaDstu2Test {
*/
@Test
public void testSearchDontReindexForUpdateWithIndexDisabled() {
BaseHapiFhirResourceDao.setDisableIncrementOnUpdateForUnitTest(true);
Patient patient;
SearchParameterMap map;
patient = new Patient();
patient.getText().setDiv("<div>DIVAAA</div>");
patient.addName().addGiven("NAMEAAA");
IIdType pId1 = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
final IIdType pId1 = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
map = new SearchParameterMap();
map.add(Constants.PARAM_CONTENT, new StringParam("NAMEAAA"));

View File

@ -45,41 +45,13 @@ public class FhirResourceDaoDstu2Test extends BaseJpaDstu2Test {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoDstu2Test.class);
@Before
public void beforeDisableResultReuse() {
myDaoConfig.setReuseCachedSearchResultsForMillis(null);
}
@After
public final void after() {
myDaoConfig.setAllowExternalReferences(new DaoConfig().isAllowExternalReferences());
myDaoConfig.setTreatReferencesAsLogical(new DaoConfig().getTreatReferencesAsLogical());
myDaoConfig.setEnforceReferentialIntegrityOnDelete(new DaoConfig().isEnforceReferentialIntegrityOnDelete());
}
/**
* See #773
*/
@Test
public void testDeleteResourceWithOutboundDeletedResources() {
myDaoConfig.setEnforceReferentialIntegrityOnDelete(false);
Organization org = new Organization();
org.setId("ORG");
org.setName("ORG");
myOrganizationDao.update(org);
Patient pat = new Patient();
pat.setId("PAT");
pat.setActive(true);
pat.setManagingOrganization(new ResourceReferenceDt("Organization/ORG"));
myPatientDao.update(pat);
myOrganizationDao.delete(new IdDt("Organization/ORG"));
myPatientDao.delete(new IdDt("Patient/PAT"));
}
private void assertGone(IIdType theId) {
try {
assertNotGone(theId);
@ -102,6 +74,11 @@ public class FhirResourceDaoDstu2Test extends BaseJpaDstu2Test {
}
}
@Before
public void beforeDisableResultReuse() {
myDaoConfig.setReuseCachedSearchResultsForMillis(null);
}
private List<String> extractNames(IBundleProvider theSearch) {
ArrayList<String> retVal = new ArrayList<String>();
for (IBaseResource next : theSearch.getResources(0, theSearch.size())) {
@ -865,6 +842,29 @@ public class FhirResourceDaoDstu2Test extends BaseJpaDstu2Test {
}
/**
* See #773
*/
@Test
public void testDeleteResourceWithOutboundDeletedResources() {
myDaoConfig.setEnforceReferentialIntegrityOnDelete(false);
Organization org = new Organization();
org.setId("ORG");
org.setName("ORG");
myOrganizationDao.update(org);
Patient pat = new Patient();
pat.setId("PAT");
pat.setActive(true);
pat.setManagingOrganization(new ResourceReferenceDt("Organization/ORG"));
myPatientDao.update(pat);
myOrganizationDao.delete(new IdDt("Organization/ORG"));
myPatientDao.delete(new IdDt("Patient/PAT"));
}
@Test
public void testDeleteThenUndelete() {
Patient patient = new Patient();

View File

@ -8,6 +8,8 @@ import java.util.List;
import javax.servlet.http.HttpServletRequest;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.entity.ResourceTable;
import org.hl7.fhir.dstu3.model.*;
import org.hl7.fhir.dstu3.model.Observation.ObservationStatus;
import org.hl7.fhir.instance.model.api.IIdType;
@ -19,6 +21,9 @@ import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.param.*;
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
import ca.uhn.fhir.util.TestUtil;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
public class FhirResourceDaoDstu3SearchFtTest extends BaseJpaDstu3Test {
@ -473,13 +478,14 @@ public class FhirResourceDaoDstu3SearchFtTest extends BaseJpaDstu3Test {
*/
@Test
public void testSearchDontReindexForUpdateWithIndexDisabled() {
BaseHapiFhirResourceDao.setDisableIncrementOnUpdateForUnitTest(true);
Patient patient;
SearchParameterMap map;
patient = new Patient();
patient.getText().setDivAsString("<div>DIVAAA</div>");
patient.addName().addGiven("NAMEAAA");
IIdType pId1 = myPatientDao.create(patient, mockSrd()).getId().toUnqualifiedVersionless();
final IIdType pId1 = myPatientDao.create(patient, mockSrd()).getId().toUnqualifiedVersionless();
map = new SearchParameterMap();
map.add(Constants.PARAM_CONTENT, new StringParam("NAMEAAA"));

View File

@ -234,6 +234,7 @@ public abstract class BaseJpaR4Test extends BaseJpaTest {
@After()
public void afterCleanupDao() {
myDaoConfig.setExpireSearchResults(new DaoConfig().isExpireSearchResults());
myDaoConfig.setEnforceReferentialIntegrityOnDelete(new DaoConfig().isEnforceReferentialIntegrityOnDelete());
myDaoConfig.setExpireSearchResultsAfterMillis(new DaoConfig().getExpireSearchResultsAfterMillis());
myDaoConfig.setReuseCachedSearchResultsForMillis(new DaoConfig().getReuseCachedSearchResultsForMillis());
myDaoConfig.setSuppressUpdatesWithNoChange(new DaoConfig().isSuppressUpdatesWithNoChange());

View File

@ -8,6 +8,8 @@ import java.util.List;
import javax.servlet.http.HttpServletRequest;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.entity.ResourceTable;
import org.hl7.fhir.r4.model.*;
import org.hl7.fhir.r4.model.Observation.ObservationStatus;
import org.hl7.fhir.instance.model.api.IIdType;
@ -19,6 +21,9 @@ import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.param.*;
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
import ca.uhn.fhir.util.TestUtil;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
public class FhirResourceDaoR4SearchFtTest extends BaseJpaR4Test {
@ -473,13 +478,14 @@ public class FhirResourceDaoR4SearchFtTest extends BaseJpaR4Test {
*/
@Test
public void testSearchDontReindexForUpdateWithIndexDisabled() {
BaseHapiFhirResourceDao.setDisableIncrementOnUpdateForUnitTest(true);
Patient patient;
SearchParameterMap map;
patient = new Patient();
patient.getText().setDivAsString("<div>DIVAAA</div>");
patient.addName().addGiven("NAMEAAA");
IIdType pId1 = myPatientDao.create(patient, mockSrd()).getId().toUnqualifiedVersionless();
final IIdType pId1 = myPatientDao.create(patient, mockSrd()).getId().toUnqualifiedVersionless();
map = new SearchParameterMap();
map.add(Constants.PARAM_CONTENT, new StringParam("NAMEAAA"));

View File

@ -1131,15 +1131,29 @@ public class FhirResourceDaoR4Test extends BaseJpaR4Test {
patient = new Patient();
patient.setId(id.getIdPart());
patient.addName().setFamily(methodName);
patient.setActive(false);
IIdType id5 = myPatientDao.update(patient).getId();
assertEquals(id.getIdPart(), id5.getIdPart());
assertEquals("3", id5.getVersionIdPart());
patient = myPatientDao.read(id.withVersion("1"));
assertEquals(true, patient.getActive());
try {
myPatientDao.read(id.withVersion("2"));
fail();
} catch (ResourceGoneException e) {
// good
}
patient = myPatientDao.read(id.withVersion("3"));
assertEquals(false, patient.getActive());
aaaa
}
@Test
public void testDeleteResource() {
int initialHistory = myPatientDao.history((Date) null, null, mySrd).size();
int initialHistory = myPatientDao.history(null, null, mySrd).size();
IIdType id1;
IIdType id2;
@ -1161,7 +1175,7 @@ public class FhirResourceDaoR4Test extends BaseJpaR4Test {
patient.addIdentifier().setSystem("ZZZZZZZ").setValue("ZZZZZZZZZ");
id2b = myPatientDao.update(patient, mySrd).getId();
}
ourLog.info("ID1:{} ID2:{} ID2b:{}", new Object[] { id1, id2, id2b });
ourLog.info("ID1:{} ID2:{} ID2b:{}", id1, id2, id2b);
SearchParameterMap params = new SearchParameterMap();
params.setLoadSynchronous(true);
@ -1182,7 +1196,7 @@ public class FhirResourceDaoR4Test extends BaseJpaR4Test {
// good
}
IBundleProvider history = myPatientDao.history((Date) null, null, mySrd);
IBundleProvider history = myPatientDao.history(null, null, mySrd);
assertEquals(4 + initialHistory, history.size().intValue());
List<IBaseResource> resources = history.getResources(0, 4);
assertNotNull(ResourceMetadataKeyEnum.DELETED_AT.get((IAnyResource) resources.get(0)));
@ -1554,7 +1568,7 @@ public class FhirResourceDaoR4Test extends BaseJpaR4Test {
}
// By type
history = myPatientDao.history((Date) null, null, mySrd);
history = myPatientDao.history(null, null, mySrd);
assertEquals(fullSize + 1, history.size().intValue());
for (int i = 0; i < fullSize; i++) {
String expected = id.withVersion(Integer.toString(fullSize + 1 - i)).getValue();
@ -1621,7 +1635,7 @@ public class FhirResourceDaoR4Test extends BaseJpaR4Test {
}
// By type
history = myPatientDao.history((Date) null, null, mySrd);
history = myPatientDao.history(null, null, mySrd);
assertEquals(fullSize + 1, history.size().intValue());
for (int i = 0; i < fullSize; i++) {
String expected = id.withVersion(Integer.toString(fullSize + 1 - i)).getValue();
@ -1672,13 +1686,13 @@ public class FhirResourceDaoR4Test extends BaseJpaR4Test {
}
@Test
public void testHistoryReflectsMetaOperations() throws Exception {
public void testHistoryReflectsMetaOperations() {
Patient inPatient = new Patient();
inPatient.addName().setFamily("version1");
inPatient.getMeta().addProfile("http://example.com/1");
IIdType id = myPatientDao.create(inPatient, mySrd).getId().toUnqualifiedVersionless();
IBundleProvider history = myPatientDao.history((Date) null, null, mySrd);
IBundleProvider history = myPatientDao.history(null, null, mySrd);
assertEquals(1, history.size().intValue());
Patient outPatient = (Patient) history.getResources(0, 1).get(0);
assertEquals("version1", inPatient.getName().get(0).getFamily());
@ -1692,7 +1706,7 @@ public class FhirResourceDaoR4Test extends BaseJpaR4Test {
inPatient.getMeta().addProfile("http://example.com/2");
myPatientDao.metaAddOperation(id, inPatient.getMeta(), mySrd);
history = myPatientDao.history((Date) null, null, mySrd);
history = myPatientDao.history(null, null, mySrd);
assertEquals(1, history.size().intValue());
outPatient = (Patient) history.getResources(0, 1).get(0);
assertEquals("version1", inPatient.getName().get(0).getFamily());
@ -1708,7 +1722,7 @@ public class FhirResourceDaoR4Test extends BaseJpaR4Test {
inPatient.getName().get(0).setFamily("version2");
myPatientDao.update(inPatient, mySrd);
history = myPatientDao.history((Date) null, null, mySrd);
history = myPatientDao.history(null, null, mySrd);
assertEquals(2, history.size().intValue());
outPatient = (Patient) history.getResources(0, 2).get(0);
assertEquals("version2", outPatient.getName().get(0).getFamily());
@ -1723,7 +1737,7 @@ public class FhirResourceDaoR4Test extends BaseJpaR4Test {
}
@Test
public void testHistoryWithDeletedResource() throws Exception {
public void testHistoryWithDeletedResource() {
String methodName = "testHistoryWithDeletedResource";
Patient patient = new Patient();
@ -1736,9 +1750,9 @@ public class FhirResourceDaoR4Test extends BaseJpaR4Test {
IBundleProvider history = myPatientDao.history(id, null, null, mySrd);
List<IBaseResource> entries = history.getResources(0, 3);
ourLog.info(((IAnyResource) entries.get(0)).getIdElement() + " - " + ((IAnyResource) entries.get(0)).getMeta().getLastUpdated());
ourLog.info(((IAnyResource) entries.get(1)).getIdElement() + " - " + ((IAnyResource) entries.get(1)).getMeta().getLastUpdated());
ourLog.info(((IAnyResource) entries.get(2)).getIdElement() + " - " + ((IAnyResource) entries.get(2)).getMeta().getLastUpdated());
ourLog.info(entries.get(0).getIdElement() + " - " + entries.get(0).getMeta().getLastUpdated());
ourLog.info(entries.get(1).getIdElement() + " - " + entries.get(1).getMeta().getLastUpdated());
ourLog.info(entries.get(2).getIdElement() + " - " + entries.get(2).getMeta().getLastUpdated());
assertEquals(3, history.size().intValue());
assertEquals(id.withVersion("3"), entries.get(0).getIdElement());
@ -1802,7 +1816,7 @@ public class FhirResourceDaoR4Test extends BaseJpaR4Test {
// No since
IBundleProvider history = myPatientDao.history((Date) null, null, mySrd);
IBundleProvider history = myPatientDao.history(null, null, mySrd);
assertEquals(1, history.size().intValue());
Patient outPatient = (Patient) history.getResources(0, 1).get(0);
assertEquals("version1", inPatient.getName().get(0).getFamily());
@ -1826,7 +1840,7 @@ public class FhirResourceDaoR4Test extends BaseJpaR4Test {
}
@Test
public void testHistoryWithInvalidId() throws Exception {
public void testHistoryWithInvalidId() {
try {
myPatientDao.history(new IdType("Patient/FOOFOOFOO"), null, null, mySrd);
fail();
@ -2204,7 +2218,7 @@ public class FhirResourceDaoR4Test extends BaseJpaR4Test {
dr01.setSubject(new Reference(patientId01));
IIdType drId01 = myDiagnosticReportDao.create(dr01, mySrd).getId();
ourLog.info("P1[{}] P2[{}] O1[{}] O2[{}] D1[{}]", new Object[] { patientId01, patientId02, obsId01, obsId02, drId01 });
ourLog.info("P1[{}] P2[{}] O1[{}] O2[{}] D1[{}]", patientId01, patientId02, obsId01, obsId02, drId01);
List<Observation> result = toList(myObservationDao.search(new SearchParameterMap(Observation.SP_SUBJECT, new ReferenceParam(patientId01.getIdPart())).setLoadSynchronous(true)));
assertEquals(1, result.size());
@ -2214,7 +2228,7 @@ public class FhirResourceDaoR4Test extends BaseJpaR4Test {
assertEquals(1, result.size());
assertEquals(obsId02.getIdPart(), result.get(0).getIdElement().getIdPart());
result = toList(myObservationDao.search(new SearchParameterMap(Observation.SP_SUBJECT, new ReferenceParam("999999999999")).setLoadSynchronous(true)));;
result = toList(myObservationDao.search(new SearchParameterMap(Observation.SP_SUBJECT, new ReferenceParam("999999999999")).setLoadSynchronous(true)));
assertEquals(0, result.size());
}
@ -2297,7 +2311,7 @@ public class FhirResourceDaoR4Test extends BaseJpaR4Test {
long id = outcome.getId().getIdPartAsLong();
TokenParam value = new TokenParam("urn:system", "001testPersistSearchParams");
List<Patient> found = toList(myPatientDao.search(new SearchParameterMap(Patient.SP_IDENTIFIER, value).setLoadSynchronous(true)));;
List<Patient> found = toList(myPatientDao.search(new SearchParameterMap(Patient.SP_IDENTIFIER, value).setLoadSynchronous(true)));
assertEquals(1, found.size());
assertEquals(id, found.get(0).getIdElement().getIdPartAsLong().longValue());
@ -2409,7 +2423,7 @@ public class FhirResourceDaoR4Test extends BaseJpaR4Test {
}
@Test
public void testReadInvalidVersion() throws Exception {
public void testReadInvalidVersion() {
String methodName = "testReadInvalidVersion";
Patient pat = new Patient();
@ -2621,7 +2635,7 @@ public class FhirResourceDaoR4Test extends BaseJpaR4Test {
id1 = myPatientDao.create(patient, mySrd).getId();
Meta metaAdd = new Meta();
metaAdd.addTag().setSystem((String) null).setCode("Dog").setDisplay("Puppies");
metaAdd.addTag().setSystem(null).setCode("Dog").setDisplay("Puppies");
metaAdd.addSecurity().setSystem("seclabel:sys:1").setCode("seclabel:code:1").setDisplay("seclabel:dis:1");
metaAdd.addProfile("http://profile/1");
myPatientDao.metaAddOperation(id1, metaAdd, mySrd);
@ -2691,7 +2705,7 @@ public class FhirResourceDaoR4Test extends BaseJpaR4Test {
{
Meta metaDel = new Meta();
metaDel.addTag().setSystem((String) null).setCode("Dog");
metaDel.addTag().setSystem(null).setCode("Dog");
metaDel.addSecurity().setSystem("seclabel:sys:1").setCode("seclabel:code:1");
metaDel.addProfile("http://profile/1");
myPatientDao.metaDeleteOperation(id1, metaDel, mySrd);
@ -3381,7 +3395,7 @@ public class FhirResourceDaoR4Test extends BaseJpaR4Test {
* Test for issue #60
*/
@Test
public void testStoreUtf8Characters() throws Exception {
public void testStoreUtf8Characters() {
Organization org = new Organization();
org.setName("測試醫院");
org.addIdentifier().setSystem("urn:system").setValue("testStoreUtf8Characters_01");
@ -3541,7 +3555,7 @@ public class FhirResourceDaoR4Test extends BaseJpaR4Test {
}
@Test
public void testTimingSearchParams() throws Exception {
public void testTimingSearchParams() {
Date before = new DateTimeType("2011-01-01T10:00:00Z").getValue();
Date middle = new DateTimeType("2011-01-02T10:00:00Z").getValue();
Date after = new DateTimeType("2011-01-03T10:00:00Z").getValue();
@ -3607,7 +3621,7 @@ public class FhirResourceDaoR4Test extends BaseJpaR4Test {
}
@Test
public void testUpdateRejectsIdWhichPointsToForcedId() throws InterruptedException {
public void testUpdateRejectsIdWhichPointsToForcedId() {
Patient p1 = new Patient();
p1.addIdentifier().setSystem("urn:system").setValue("testUpdateRejectsIdWhichPointsToForcedId01");
p1.addName().setFamily("Tester").addGiven("testUpdateRejectsIdWhichPointsToForcedId01");

View File

@ -270,6 +270,46 @@ public class FhirResourceDaoR4ValidateTest extends BaseJpaR4Test {
}
@Test
public void testValidateForDeleteWithReferentialIntegrityDisabled() {
myDaoConfig.setEnforceReferentialIntegrityOnDelete(false);
String methodName = "testValidateForDelete";
Organization org = new Organization();
org.setName(methodName);
IIdType orgId = myOrganizationDao.create(org, mySrd).getId().toUnqualifiedVersionless();
Patient pat = new Patient();
pat.addName().setFamily(methodName);
pat.getManagingOrganization().setReference(orgId.getValue());
IIdType patId = myPatientDao.create(pat, mySrd).getId().toUnqualifiedVersionless();
myOrganizationDao.validate(null, orgId, null, null, ValidationModeEnum.DELETE, null, mySrd);
myDaoConfig.setEnforceReferentialIntegrityOnDelete(true);
try {
myOrganizationDao.validate(null, orgId, null, null, ValidationModeEnum.DELETE, null, mySrd);
fail();
} catch (ResourceVersionConflictException e) {
// good
}
myDaoConfig.setEnforceReferentialIntegrityOnDelete(false);
myOrganizationDao.read(orgId);
myOrganizationDao.delete(orgId);
try {
myOrganizationDao.read(orgId);
fail();
} catch (ResourceGoneException e) {
// good
}
}
private IBaseResource findResourceByIdInBundle(Bundle vss, String name) {
IBaseResource retVal = null;
for (BundleEntryComponent next : vss.getEntry()) {

View File

@ -1,45 +1,48 @@
package ca.uhn.fhir.jpa.provider;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.junit.*;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.dao.dstu2.BaseJpaDstu2Test;
import ca.uhn.fhir.jpa.rp.dstu2.*;
import ca.uhn.fhir.jpa.rp.dstu2.ObservationResourceProvider;
import ca.uhn.fhir.jpa.rp.dstu2.OrganizationResourceProvider;
import ca.uhn.fhir.jpa.rp.dstu2.PatientResourceProvider;
import ca.uhn.fhir.jpa.testutil.RandomServerPortProvider;
import ca.uhn.fhir.model.dstu2.resource.Bundle;
import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry;
import ca.uhn.fhir.model.dstu2.resource.Patient;
import ca.uhn.fhir.model.dstu2.valueset.*;
import ca.uhn.fhir.model.dstu2.valueset.AdministrativeGenderEnum;
import ca.uhn.fhir.model.dstu2.valueset.BundleTypeEnum;
import ca.uhn.fhir.model.dstu2.valueset.HTTPVerbEnum;
import ca.uhn.fhir.rest.api.EncodingEnum;
import ca.uhn.fhir.rest.client.api.IGenericClient;
import ca.uhn.fhir.rest.client.interceptor.SimpleRequestHeaderInterceptor;
import ca.uhn.fhir.rest.server.RestfulServer;
import ca.uhn.fhir.util.TestUtil;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
public class SystemProviderTransactionSearchDstu2Test extends BaseJpaDstu2Test {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SystemProviderTransactionSearchDstu2Test.class);
private static RestfulServer myRestServer;
private static IGenericClient ourClient;
private static FhirContext ourCtx;
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SystemProviderTransactionSearchDstu2Test.class);
private static Server ourServer;
private static String ourServerBase;
private SimpleRequestHeaderInterceptor mySimpleHeaderInterceptor;
@SuppressWarnings("deprecation")
@After
public void after() {
@ -53,7 +56,7 @@ public class SystemProviderTransactionSearchDstu2Test extends BaseJpaDstu2Test {
mySimpleHeaderInterceptor = new SimpleRequestHeaderInterceptor();
ourClient.registerInterceptor(mySimpleHeaderInterceptor);
}
@Before
public void beforeStartServer() throws Exception {
if (myRestServer == null) {
@ -96,11 +99,11 @@ public class SystemProviderTransactionSearchDstu2Test extends BaseJpaDstu2Test {
ourClient = ourCtx.newRestfulGenericClient(ourServerBase);
myRestServer = restServer;
}
myRestServer.setDefaultResponseEncoding(EncodingEnum.XML);
myRestServer.setPagingProvider(myPagingProvider);
}
private List<String> create20Patients() {
List<String> ids = new ArrayList<String>();
@ -108,7 +111,7 @@ public class SystemProviderTransactionSearchDstu2Test extends BaseJpaDstu2Test {
Patient patient = new Patient();
patient.setGender(AdministrativeGenderEnum.MALE);
patient.addIdentifier().setSystem("urn:foo").setValue("A");
patient.addName().addFamily("abcdefghijklmnopqrstuvwxyz".substring(i, i+1));
patient.addName().addFamily("abcdefghijklmnopqrstuvwxyz".substring(i, i + 1));
String id = myPatientDao.create(patient).getId().toUnqualifiedVersionless().getValue();
ids.add(id);
}
@ -116,9 +119,9 @@ public class SystemProviderTransactionSearchDstu2Test extends BaseJpaDstu2Test {
}
@Test
public void testBatchWithGetHardLimitLargeSynchronous() throws Exception {
public void testBatchWithGetHardLimitLargeSynchronous() {
List<String> ids = create20Patients();
Bundle input = new Bundle();
input.setType(BundleTypeEnum.BATCH);
input
@ -126,12 +129,12 @@ public class SystemProviderTransactionSearchDstu2Test extends BaseJpaDstu2Test {
.getRequest()
.setMethod(HTTPVerbEnum.GET)
.setUrl("Patient?_count=5&_sort=name");
myDaoConfig.setMaximumSearchResultCountInTransaction(100);
Bundle output = ourClient.transaction().withBundle(input).execute();
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(output));
assertEquals(1, output.getEntry().size());
Bundle respBundle = (Bundle) output.getEntry().get(0).getResource();
assertEquals(5, respBundle.getEntry().size());
@ -139,11 +142,11 @@ public class SystemProviderTransactionSearchDstu2Test extends BaseJpaDstu2Test {
List<String> actualIds = toIds(respBundle);
assertThat(actualIds, contains(ids.subList(0, 5).toArray(new String[0])));
}
@Test
public void testBatchWithGetNormalSearch() throws Exception {
public void testBatchWithGetNormalSearch() {
List<String> ids = create20Patients();
Bundle input = new Bundle();
input.setType(BundleTypeEnum.BATCH);
input
@ -151,16 +154,16 @@ public class SystemProviderTransactionSearchDstu2Test extends BaseJpaDstu2Test {
.getRequest()
.setMethod(HTTPVerbEnum.GET)
.setUrl("Patient?_count=5&_sort=name");
Bundle output = ourClient.transaction().withBundle(input).execute();
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(output));
assertEquals(1, output.getEntry().size());
Bundle respBundle = (Bundle) output.getEntry().get(0).getResource();
assertEquals(5, respBundle.getEntry().size());
List<String> actualIds = toIds(respBundle);
assertThat(actualIds, contains(ids.subList(0, 5).toArray(new String[0])));
String nextPageLink = respBundle.getLink("next").getUrl();
output = ourClient.loadPage().byUrl(nextPageLink).andReturnBundle(Bundle.class).execute();
respBundle = output;
@ -173,10 +176,10 @@ public class SystemProviderTransactionSearchDstu2Test extends BaseJpaDstu2Test {
* 30 searches in one batch! Whoa!
*/
@Test
public void testBatchWithManyGets() throws Exception {
public void testBatchWithManyGets() {
List<String> ids = create20Patients();
Bundle input = new Bundle();
input.setType(BundleTypeEnum.BATCH);
for (int i = 0; i < 30; i++) {
@ -186,10 +189,10 @@ public class SystemProviderTransactionSearchDstu2Test extends BaseJpaDstu2Test {
.setMethod(HTTPVerbEnum.GET)
.setUrl("Patient?_count=5&identifier=urn:foo|A,AAAAA" + i);
}
Bundle output = ourClient.transaction().withBundle(input).execute();
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(output));
assertEquals(30, output.getEntry().size());
for (int i = 0; i < 30; i++) {
Bundle respBundle = (Bundle) output.getEntry().get(i).getResource();
@ -201,22 +204,22 @@ public class SystemProviderTransactionSearchDstu2Test extends BaseJpaDstu2Test {
}
@Test
public void testTransactionWithGetHardLimitLargeSynchronous() throws Exception {
public void testTransactionWithGetHardLimitLargeSynchronous() {
List<String> ids = create20Patients();
Bundle input = new Bundle();
input.setType(BundleTypeEnum.TRANSACTION);
input
.addEntry()
.getRequest()
.setMethod(HTTPVerbEnum.GET)
.setUrl("Patient?_count=5");
.setUrl("Patient?_count=5&_sort=_id");
myDaoConfig.setMaximumSearchResultCountInTransaction(100);
Bundle output = ourClient.transaction().withBundle(input).execute();
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(output));
assertEquals(1, output.getEntry().size());
Bundle respBundle = (Bundle) output.getEntry().get(0).getResource();
assertEquals(5, respBundle.getEntry().size());
@ -224,11 +227,11 @@ public class SystemProviderTransactionSearchDstu2Test extends BaseJpaDstu2Test {
List<String> actualIds = toIds(respBundle);
assertThat(actualIds, contains(ids.subList(0, 5).toArray(new String[0])));
}
@Test
public void testTransactionWithGetNormalSearch() throws Exception {
public void testTransactionWithGetNormalSearch() {
List<String> ids = create20Patients();
Bundle input = new Bundle();
input.setType(BundleTypeEnum.TRANSACTION);
input
@ -236,16 +239,16 @@ public class SystemProviderTransactionSearchDstu2Test extends BaseJpaDstu2Test {
.getRequest()
.setMethod(HTTPVerbEnum.GET)
.setUrl("Patient?_count=5&_sort=name");
Bundle output = ourClient.transaction().withBundle(input).execute();
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(output));
assertEquals(1, output.getEntry().size());
Bundle respBundle = (Bundle) output.getEntry().get(0).getResource();
assertEquals(5, respBundle.getEntry().size());
List<String> actualIds = toIds(respBundle);
assertThat(actualIds, contains(ids.subList(0, 5).toArray(new String[0])));
String nextPageLink = respBundle.getLink("next").getUrl();
output = ourClient.loadPage().byUrl(nextPageLink).andReturnBundle(Bundle.class).execute();
respBundle = output;
@ -258,10 +261,10 @@ public class SystemProviderTransactionSearchDstu2Test extends BaseJpaDstu2Test {
* 30 searches in one Transaction! Whoa!
*/
@Test
public void testTransactionWithManyGets() throws Exception {
public void testTransactionWithManyGets() {
List<String> ids = create20Patients();
Bundle input = new Bundle();
input.setType(BundleTypeEnum.TRANSACTION);
for (int i = 0; i < 30; i++) {
@ -271,10 +274,10 @@ public class SystemProviderTransactionSearchDstu2Test extends BaseJpaDstu2Test {
.setMethod(HTTPVerbEnum.GET)
.setUrl("Patient?_count=5&identifier=urn:foo|A,AAAAA" + i);
}
Bundle output = ourClient.transaction().withBundle(input).execute();
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(output));
assertEquals(30, output.getEntry().size());
for (int i = 0; i < 30; i++) {
Bundle respBundle = (Bundle) output.getEntry().get(i).getResource();

View File

@ -126,7 +126,7 @@ public class SystemProviderTransactionSearchDstu3Test extends BaseJpaDstu3Test {
}
@Test
public void testBatchWithGetHardLimitLargeSynchronous() throws Exception {
public void testBatchWithGetHardLimitLargeSynchronous() {
List<String> ids = create20Patients();
Bundle input = new Bundle();
@ -135,7 +135,7 @@ public class SystemProviderTransactionSearchDstu3Test extends BaseJpaDstu3Test {
.addEntry()
.getRequest()
.setMethod(HTTPVerb.GET)
.setUrl("Patient?_count=5");
.setUrl("Patient?_count=5&_sort=_id");
myDaoConfig.setMaximumSearchResultCountInTransaction(100);
@ -151,7 +151,7 @@ public class SystemProviderTransactionSearchDstu3Test extends BaseJpaDstu3Test {
}
@Test
public void testBatchWithGetNormalSearch() throws Exception {
public void testBatchWithGetNormalSearch() {
List<String> ids = create20Patients();
Bundle input = new Bundle();
@ -183,7 +183,7 @@ public class SystemProviderTransactionSearchDstu3Test extends BaseJpaDstu3Test {
* 30 searches in one batch! Whoa!
*/
@Test
public void testBatchWithManyGets() throws Exception {
public void testBatchWithManyGets() {
List<String> ids = create20Patients();
@ -211,7 +211,7 @@ public class SystemProviderTransactionSearchDstu3Test extends BaseJpaDstu3Test {
}
@Test
public void testTransactionWithGetHardLimitLargeSynchronous() throws Exception {
public void testTransactionWithGetHardLimitLargeSynchronous() {
List<String> ids = create20Patients();
Bundle input = new Bundle();
@ -220,7 +220,7 @@ public class SystemProviderTransactionSearchDstu3Test extends BaseJpaDstu3Test {
.addEntry()
.getRequest()
.setMethod(HTTPVerb.GET)
.setUrl("Patient?_count=5");
.setUrl("Patient?_count=5&_sort=_id");
myDaoConfig.setMaximumSearchResultCountInTransaction(100);
@ -236,7 +236,7 @@ public class SystemProviderTransactionSearchDstu3Test extends BaseJpaDstu3Test {
}
@Test
public void testTransactionWithGetNormalSearch() throws Exception {
public void testTransactionWithGetNormalSearch() {
List<String> ids = create20Patients();
Bundle input = new Bundle();
@ -268,7 +268,7 @@ public class SystemProviderTransactionSearchDstu3Test extends BaseJpaDstu3Test {
* 30 searches in one Transaction! Whoa!
*/
@Test
public void testTransactionWithManyGets() throws Exception {
public void testTransactionWithManyGets() {
List<String> ids = create20Patients();

View File

@ -2,6 +2,7 @@ package ca.uhn.fhir.jpa.provider.r4;
import ca.uhn.fhir.jpa.config.TestR4Config;
import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.entity.ResourceHistoryTable;
import ca.uhn.fhir.jpa.entity.Search;
import ca.uhn.fhir.jpa.search.SearchCoordinatorSvcImpl;
import ca.uhn.fhir.jpa.util.StopWatch;
@ -54,6 +55,8 @@ import org.junit.*;
import org.springframework.test.util.AopTestUtils;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import java.io.BufferedReader;
import java.io.IOException;
@ -1642,31 +1645,6 @@ public class ResourceProviderR4Test extends BaseResourceProviderR4Test {
}
}
// private void delete(String theResourceType, String theParamName, String theParamValue) {
// Bundle resources;
// do {
// IQuery<Bundle> forResource = myClient.search().forResource(theResourceType);
// if (theParamName != null) {
// forResource = forResource.where(new StringClientParam(theParamName).matches().value(theParamValue));
// }
// resources = forResource.execute();
// for (IResource next : resources.toListOfResources()) {
// ourLog.info("Deleting resource: {}", next.getId());
// myClient.delete().resource(next).execute();
// }
// } while (resources.size() > 0);
// }
//
// private void deleteToken(String theResourceType, String theParamName, String theParamSystem, String theParamValue)
// {
// Bundle resources = myClient.search().forResource(theResourceType).where(new
// TokenClientParam(theParamName).exactly().systemAndCode(theParamSystem, theParamValue)).execute();
// for (IResource next : resources.toListOfResources()) {
// ourLog.info("Deleting resource: {}", next.getId());
// myClient.delete().resource(next).execute();
// }
// }
@Test
public void testHasParameter() throws Exception {
IIdType pid0;
@ -1704,6 +1682,31 @@ public class ResourceProviderR4Test extends BaseResourceProviderR4Test {
assertThat(ids, contains(pid0.getValue()));
}
// private void delete(String theResourceType, String theParamName, String theParamValue) {
// Bundle resources;
// do {
// IQuery<Bundle> forResource = myClient.search().forResource(theResourceType);
// if (theParamName != null) {
// forResource = forResource.where(new StringClientParam(theParamName).matches().value(theParamValue));
// }
// resources = forResource.execute();
// for (IResource next : resources.toListOfResources()) {
// ourLog.info("Deleting resource: {}", next.getId());
// myClient.delete().resource(next).execute();
// }
// } while (resources.size() > 0);
// }
//
// private void deleteToken(String theResourceType, String theParamName, String theParamSystem, String theParamValue)
// {
// Bundle resources = myClient.search().forResource(theResourceType).where(new
// TokenClientParam(theParamName).exactly().systemAndCode(theParamSystem, theParamValue)).execute();
// for (IResource next : resources.toListOfResources()) {
// ourLog.info("Deleting resource: {}", next.getId());
// myClient.delete().resource(next).execute();
// }
// }
@Test
public void testHasParameterNoResults() throws Exception {
@ -2347,6 +2350,54 @@ public class ResourceProviderR4Test extends BaseResourceProviderR4Test {
}
}
@Test
public void testRetrieveMissingVersionsDoesntCrashSearch() {
Patient p1 = new Patient();
p1.setActive(true);
final IIdType id1 = myClient.create().resource(p1).execute().getId();
Patient p2 = new Patient();
p2.setActive(false);
IIdType id2 = myClient.create().resource(p2).execute().getId();
new TransactionTemplate(myTxManager).execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
ResourceHistoryTable version = myResourceHistoryTableDao.findForIdAndVersion(id1.getIdPartAsLong(), 1);
myResourceHistoryTableDao.delete(version);
}
});
Bundle bundle = myClient.search().forResource("Patient").returnBundle(Bundle.class).execute();
assertEquals(2, bundle.getTotal());
assertEquals(1, bundle.getEntry().size());
assertEquals(id2.getIdPart(), bundle.getEntry().get(0).getResource().getIdElement().getIdPart());
}
@Test
public void testRetrieveMissingVersionsDoesntCrashHistory() {
Patient p1 = new Patient();
p1.setActive(true);
final IIdType id1 = myClient.create().resource(p1).execute().getId();
Patient p2 = new Patient();
p2.setActive(false);
IIdType id2 = myClient.create().resource(p2).execute().getId();
new TransactionTemplate(myTxManager).execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
ResourceHistoryTable version = myResourceHistoryTableDao.findForIdAndVersion(id1.getIdPartAsLong(), 1);
myResourceHistoryTableDao.delete(version);
}
});
Bundle bundle = myClient.history().onServer().andReturnBundle(Bundle.class).execute();
assertEquals(1, bundle.getTotal());
assertEquals(1, bundle.getEntry().size());
assertEquals(id2.getIdPart(), bundle.getEntry().get(0).getResource().getIdElement().getIdPart());
}
@Test
public void testSaveAndRetrieveExistingNarrativeJson() {
Patient p1 = new Patient();

View File

@ -33,11 +33,11 @@ import ca.uhn.fhir.util.TestUtil;
public class SystemProviderTransactionSearchR4Test extends BaseJpaR4Test {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SystemProviderTransactionSearchR4Test.class);
private static RestfulServer myRestServer;
private static IGenericClient ourClient;
private static FhirContext ourCtx;
private static CloseableHttpClient ourHttpClient;
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SystemProviderTransactionSearchR4Test.class);
private static Server ourServer;
private static String ourServerBase;
private SimpleRequestHeaderInterceptor mySimpleHeaderInterceptor;
@ -116,17 +116,19 @@ public class SystemProviderTransactionSearchR4Test extends BaseJpaR4Test {
List<String> ids = new ArrayList<String>();
for (int i = 0; i < 20; i++) {
Patient patient = new Patient();
char letter = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".charAt(i);
patient.setId("" + letter);
patient.setGender(AdministrativeGender.MALE);
patient.addIdentifier().setSystem("urn:foo").setValue("A");
patient.addName().setFamily("abcdefghijklmnopqrstuvwxyz".substring(i, i+1));
String id = myPatientDao.create(patient).getId().toUnqualifiedVersionless().getValue();
String id = myPatientDao.update(patient).getId().toUnqualifiedVersionless().getValue();
ids.add(id);
}
return ids;
}
@Test
public void testBatchWithGetHardLimitLargeSynchronous() throws Exception {
public void testBatchWithGetHardLimitLargeSynchronous() {
List<String> ids = create20Patients();
Bundle input = new Bundle();
@ -135,7 +137,7 @@ public class SystemProviderTransactionSearchR4Test extends BaseJpaR4Test {
.addEntry()
.getRequest()
.setMethod(HTTPVerb.GET)
.setUrl("Patient?_count=5");
.setUrl("Patient?_count=5&_sort=_id");
myDaoConfig.setMaximumSearchResultCountInTransaction(100);
@ -151,7 +153,7 @@ public class SystemProviderTransactionSearchR4Test extends BaseJpaR4Test {
}
@Test
public void testBatchWithGetNormalSearch() throws Exception {
public void testBatchWithGetNormalSearch() {
List<String> ids = create20Patients();
Bundle input = new Bundle();
@ -183,7 +185,7 @@ public class SystemProviderTransactionSearchR4Test extends BaseJpaR4Test {
* 30 searches in one batch! Whoa!
*/
@Test
public void testBatchWithManyGets() throws Exception {
public void testBatchWithManyGets() {
List<String> ids = create20Patients();
@ -211,7 +213,7 @@ public class SystemProviderTransactionSearchR4Test extends BaseJpaR4Test {
}
@Test
public void testTransactionWithGetHardLimitLargeSynchronous() throws Exception {
public void testTransactionWithGetHardLimitLargeSynchronous() {
List<String> ids = create20Patients();
Bundle input = new Bundle();
@ -220,7 +222,7 @@ public class SystemProviderTransactionSearchR4Test extends BaseJpaR4Test {
.addEntry()
.getRequest()
.setMethod(HTTPVerb.GET)
.setUrl("Patient?_count=5");
.setUrl("Patient?_count=5&_sort=_id");
myDaoConfig.setMaximumSearchResultCountInTransaction(100);
@ -236,7 +238,7 @@ public class SystemProviderTransactionSearchR4Test extends BaseJpaR4Test {
}
@Test
public void testTransactionWithGetNormalSearch() throws Exception {
public void testTransactionWithGetNormalSearch() {
List<String> ids = create20Patients();
Bundle input = new Bundle();
@ -268,7 +270,7 @@ public class SystemProviderTransactionSearchR4Test extends BaseJpaR4Test {
* 30 searches in one Transaction! Whoa!
*/
@Test
public void testTransactionWithManyGets() throws Exception {
public void testTransactionWithManyGets() {
List<String> ids = create20Patients();

View File

@ -27,6 +27,7 @@ import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.*;
import ca.uhn.fhir.util.CollectionUtil;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IPrimitiveType;
@ -308,6 +309,29 @@ public abstract class BaseResourceReturningMethodBinding extends BaseMethodBindi
}
}
/*
* Remove any null entries in the list - This generally shouldn't happen but can if
* data has been manually purged from the JPA database
*/
boolean hasNull = false;
for (IBaseResource next : resourceList) {
if (next == null) {
hasNull = true;
break;
}
}
if (hasNull) {
for (Iterator<IBaseResource> iter = resourceList.iterator(); iter.hasNext(); ) {
if (iter.next() == null) {
iter.remove();
}
}
}
/*
* Make sure all returned resources have an ID (if not, this is a bug
* in the user server code)
*/
for (IBaseResource next : resourceList) {
if (next.getIdElement() == null || next.getIdElement().isEmpty()) {
if (!(next instanceof BaseOperationOutcome)) {

View File

@ -1,9 +1,11 @@
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} [%file:%line] - %msg%n
</pattern>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} [%file:%line] %msg%n</pattern>
</encoder>
</appender>

View File

@ -62,6 +62,12 @@
can be useful in order to allow interceptors to
change payload contents being saved.
</action>
<action type="fix">
A bug was fixed in the JPA server when performing a validate operation with a mode
of DELETE on a server with referential integrity disabled, the validate operation would delete
resource reference indexes as though the delete was actually happening, which negatively
affected searching for the resource being validated.
</action>
</release>
<release version="3.1.0" date="2017-11-23">
<action type="add">