Transaction with conditional delete and update on the same resource should not fail (#5318)
* Transaction with conditional delete and update on the same resource should not fail - test * Transaction with conditional delete and update on the same resource should not fail - implementation * Transaction with conditional delete and update on the same resource should not fail - added changelog * Transaction with conditional delete and update on the same resource should not fail - fixes
This commit is contained in:
parent
8b7c9f1453
commit
f94295d46c
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
type: fix
|
||||||
|
issue: 5316
|
||||||
|
jira: SMILE-7168
|
||||||
|
title: "Previously, performing a FHIR transaction containing both a conditional delete and a conditional update
|
||||||
|
on the same resource would fail. This has been fixed."
|
|
@ -1544,7 +1544,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> extends BaseStora
|
||||||
provenance = historyEntry.getProvenance();
|
provenance = historyEntry.getProvenance();
|
||||||
}
|
}
|
||||||
if (provenance == null) {
|
if (provenance == null) {
|
||||||
provenance = new ResourceHistoryProvenanceEntity();
|
provenance = historyEntry.toProvenance();
|
||||||
}
|
}
|
||||||
provenance.setResourceHistoryTable(historyEntry);
|
provenance.setResourceHistoryTable(historyEntry);
|
||||||
provenance.setResourceTable(theEntity);
|
provenance.setResourceTable(theEntity);
|
||||||
|
|
|
@ -111,6 +111,9 @@ public class ResourceHistoryTable extends BaseHasResource implements Serializabl
|
||||||
@Column(name = "REQUEST_ID", length = Constants.REQUEST_ID_LENGTH, nullable = true)
|
@Column(name = "REQUEST_ID", length = Constants.REQUEST_ID_LENGTH, nullable = true)
|
||||||
private String myRequestId;
|
private String myRequestId;
|
||||||
|
|
||||||
|
@Transient
|
||||||
|
private transient ResourceHistoryProvenanceEntity myNewHistoryProvenanceEntity;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*/
|
*/
|
||||||
|
@ -302,4 +305,17 @@ public class ResourceHistoryTable extends BaseHasResource implements Serializabl
|
||||||
public boolean hasResource() {
|
public boolean hasResource() {
|
||||||
return myResource != null || myResourceTextVc != null;
|
return myResource != null || myResourceTextVc != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method creates a new HistoryProvenance entity, or might reuse the current one if we've
|
||||||
|
* already created one in the current transaction. This is because we can only increment
|
||||||
|
* the version once in a DB transaction (since hibernate manages that number) so creating
|
||||||
|
* multiple {@link ResourceHistoryProvenanceEntity} entities will result in a constraint error.
|
||||||
|
*/
|
||||||
|
public ResourceHistoryProvenanceEntity toProvenance() {
|
||||||
|
if (myNewHistoryProvenanceEntity == null) {
|
||||||
|
myNewHistoryProvenanceEntity = new ResourceHistoryProvenanceEntity();
|
||||||
|
}
|
||||||
|
return myNewHistoryProvenanceEntity;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,11 +27,11 @@ import static org.apache.commons.lang3.StringUtils.countMatches;
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
import static org.hamcrest.Matchers.containsString;
|
import static org.hamcrest.Matchers.containsString;
|
||||||
import static org.hamcrest.Matchers.endsWith;
|
import static org.hamcrest.Matchers.endsWith;
|
||||||
import static org.hamcrest.Matchers.in;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
import static org.junit.jupiter.api.Assertions.fail;
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
public class FhirSystemDaoTransactionR5Test extends BaseJpaR5Test {
|
public class FhirSystemDaoTransactionR5Test extends BaseJpaR5Test {
|
||||||
|
|
||||||
|
@ -451,12 +451,22 @@ public class FhirSystemDaoTransactionR5Test extends BaseJpaR5Test {
|
||||||
/**
|
/**
|
||||||
* If a conditional delete and conditional update are both used on the same condition,
|
* If a conditional delete and conditional update are both used on the same condition,
|
||||||
* the update should win.
|
* the update should win.
|
||||||
|
* We need to test this scenario with both empty and non-empty RequestDetails.requestId parameter,
|
||||||
|
* as providing RequestDetails.requestId previously caused javax.persistence.EntityExistsException
|
||||||
|
* during persistence of ResourceHistoryProvenanceEntity.
|
||||||
|
*
|
||||||
|
* @param theReturnRequestId if RequestDetails.requestId should return non-null value
|
||||||
*/
|
*/
|
||||||
@Test
|
@ParameterizedTest
|
||||||
public void testConditionalDeleteAndConditionalUpdateOnSameResource() {
|
@ValueSource(booleans = {true, false})
|
||||||
|
public void createBundle_withConditionalDeleteAndConditionalUpdateOnSameResource_updatesResource(boolean theReturnRequestId) {
|
||||||
Bundle outcome;
|
Bundle outcome;
|
||||||
Patient actual;
|
Patient actual;
|
||||||
|
|
||||||
|
if (theReturnRequestId) {
|
||||||
|
when(mySrd.getRequestId()).thenReturn("requestId");
|
||||||
|
}
|
||||||
|
|
||||||
// First pass (resource doesn't already exist)
|
// First pass (resource doesn't already exist)
|
||||||
|
|
||||||
outcome = mySystemDao.transaction(mySrd, createBundleWithConditionalDeleteAndConditionalUpdateOnSameResource(myFhirContext));
|
outcome = mySystemDao.transaction(mySrd, createBundleWithConditionalDeleteAndConditionalUpdateOnSameResource(myFhirContext));
|
||||||
|
|
Loading…
Reference in New Issue