Database Partition Mode Merge 3 (#6535)
* Start mods for round 2 * Work on changes * Work on build * Work on tests * Test fixes * Test fixes * Test fixes * Add dump * potless * Cleanup * Cleanup * Work on mock validation support * Test fixes * Test fixes * Test fixes * Test fix * Test fixes * Test fix * Test fixes * Test fixes * Test fixes * Test fix * Test fixes * Remove redundant test * Compile fixes * Test fix * Add javadocs * Rename class * Spotless * Test fixes * Compile fix * Add test logging * Add test logging * Work on tracking down intermittent * Intermittent test fix * Add logging for another intermittent * Merge master * Cleanup * Work on tests * Work on tests * Test fixes * Test fix * Test fixes * Test fixes * Cleanup * Merge issues * HAPI version bump * Test fix
This commit is contained in:
parent
28d4f65d79
commit
a999cb32c5
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>7.7.13-SNAPSHOT</version>
|
||||
<version>7.7.14-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.7.13-SNAPSHOT</version>
|
||||
<version>7.7.14-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.7.13-SNAPSHOT</version>
|
||||
<version>7.7.14-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-bom</artifactId>
|
||||
<version>7.7.13-SNAPSHOT</version>
|
||||
<version>7.7.14-SNAPSHOT</version>
|
||||
|
||||
<packaging>pom</packaging>
|
||||
<name>HAPI FHIR BOM</name>
|
||||
|
@ -12,7 +12,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.7.13-SNAPSHOT</version>
|
||||
<version>7.7.14-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>7.7.13-SNAPSHOT</version>
|
||||
<version>7.7.14-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.7.13-SNAPSHOT</version>
|
||||
<version>7.7.14-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-cli</artifactId>
|
||||
<version>7.7.13-SNAPSHOT</version>
|
||||
<version>7.7.14-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>7.7.13-SNAPSHOT</version>
|
||||
<version>7.7.14-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.7.13-SNAPSHOT</version>
|
||||
<version>7.7.14-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.7.13-SNAPSHOT</version>
|
||||
<version>7.7.14-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.7.13-SNAPSHOT</version>
|
||||
<version>7.7.14-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.7.13-SNAPSHOT</version>
|
||||
<version>7.7.14-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>7.7.13-SNAPSHOT</version>
|
||||
<version>7.7.14-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.7.13-SNAPSHOT</version>
|
||||
<version>7.7.14-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.7.13-SNAPSHOT</version>
|
||||
<version>7.7.14-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.7.13-SNAPSHOT</version>
|
||||
<version>7.7.14-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.7.13-SNAPSHOT</version>
|
||||
<version>7.7.14-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.7.13-SNAPSHOT</version>
|
||||
<version>7.7.14-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -111,9 +111,9 @@ public class Batch2DaoSvcImpl implements IBatch2DaoSvc {
|
|||
}
|
||||
|
||||
private static TypedResourcePid typedPidFromQueryArray(Object[] thePidTypeDateArray) {
|
||||
JpaPid pid = (JpaPid) thePidTypeDateArray[0];
|
||||
String resourceType = (String) thePidTypeDateArray[1];
|
||||
Long pid = (Long) thePidTypeDateArray[0];
|
||||
return new TypedResourcePid(resourceType, JpaPid.fromId(pid));
|
||||
return new TypedResourcePid(resourceType, pid);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
|
|
|
@ -40,7 +40,6 @@ import java.util.Collection;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.slf4j.LoggerFactory.getLogger;
|
||||
|
||||
|
@ -110,10 +109,10 @@ public class ResourceVersionSvcDaoImpl implements IResourceVersionSvc {
|
|||
private ResourcePersistentIdMap getIdsOfExistingResources(
|
||||
RequestPartitionId thePartitionId, Collection<IIdType> theIds) {
|
||||
// these are the found Ids that were in the db
|
||||
ResourcePersistentIdMap retval = new ResourcePersistentIdMap();
|
||||
ResourcePersistentIdMap retVal = new ResourcePersistentIdMap();
|
||||
|
||||
if (theIds == null || theIds.isEmpty()) {
|
||||
return retval;
|
||||
return retVal;
|
||||
}
|
||||
|
||||
Map<IIdType, IResourceLookup<JpaPid>> identities = myIdHelperService.resolveResourceIdentities(
|
||||
|
@ -121,39 +120,36 @@ public class ResourceVersionSvcDaoImpl implements IResourceVersionSvc {
|
|||
new ArrayList<>(theIds),
|
||||
ResolveIdentityMode.includeDeleted().cacheOk());
|
||||
|
||||
// we'll use this map to fetch pids that require versions
|
||||
HashMap<Long, JpaPid> pidsToVersionToResourcePid = new HashMap<>();
|
||||
Map<String, JpaPid> entriesWithoutVersion = new HashMap<>(identities.size());
|
||||
|
||||
// fill in our map
|
||||
for (IResourceLookup<JpaPid> identity : identities.values()) {
|
||||
JpaPid pid = identity.getPersistentId();
|
||||
if (pid.getVersion() == null) {
|
||||
pidsToVersionToResourcePid.put(pid.getId(), pid);
|
||||
for (Map.Entry<IIdType, IResourceLookup<JpaPid>> entry : identities.entrySet()) {
|
||||
IResourceLookup<JpaPid> lookup = entry.getValue();
|
||||
JpaPid persistentId = lookup.getPersistentId();
|
||||
retVal.put(entry.getKey(), persistentId);
|
||||
if (persistentId.getVersion() == null) {
|
||||
entriesWithoutVersion.put(
|
||||
entry.getKey().toUnqualifiedVersionless().getValue(), persistentId);
|
||||
}
|
||||
Optional<IIdType> idOp = theIds.stream()
|
||||
.filter(i ->
|
||||
i.getIdPart().equals(pid.getAssociatedResourceId().getIdPart()))
|
||||
.findFirst();
|
||||
// this should always be present
|
||||
// since it was passed in.
|
||||
// but land of optionals...
|
||||
idOp.ifPresent(id -> retval.put(id, pid));
|
||||
}
|
||||
|
||||
// set any versions we don't already have
|
||||
if (!pidsToVersionToResourcePid.isEmpty()) {
|
||||
if (!entriesWithoutVersion.isEmpty()) {
|
||||
Collection<Object[]> resourceEntries =
|
||||
myResourceTableDao.getResourceVersionsForPid(new ArrayList<>(pidsToVersionToResourcePid.keySet()));
|
||||
myResourceTableDao.getResourceVersionsForPid(entriesWithoutVersion.values());
|
||||
|
||||
for (Object[] nextRecord : resourceEntries) {
|
||||
// order matters!
|
||||
Long retPid = (Long) nextRecord[0];
|
||||
JpaPid retPid = (JpaPid) nextRecord[0];
|
||||
String resType = (String) nextRecord[1];
|
||||
Long version = (Long) nextRecord[2];
|
||||
pidsToVersionToResourcePid.get(retPid).setVersion(version);
|
||||
String fhirId = (String) nextRecord[2];
|
||||
Long version = (Long) nextRecord[3];
|
||||
JpaPid jpaPid = entriesWithoutVersion.get(resType + "/" + fhirId);
|
||||
if (jpaPid != null) {
|
||||
jpaPid.setVersion(version);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
return retVal;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ import ca.uhn.fhir.jpa.dao.expunge.ResourceTableFKProvider;
|
|||
import ca.uhn.fhir.jpa.dao.tx.IHapiTransactionService;
|
||||
import ca.uhn.fhir.jpa.delete.batch2.DeleteExpungeSqlBuilder;
|
||||
import ca.uhn.fhir.jpa.delete.batch2.DeleteExpungeSvcImpl;
|
||||
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
||||
import ca.uhn.fhir.jpa.searchparam.MatchUrlService;
|
||||
import jakarta.persistence.EntityManager;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
@ -64,8 +65,9 @@ public class Batch2SupportConfig {
|
|||
ResourceTableFKProvider theResourceTableFKProvider,
|
||||
JpaStorageSettings theStorageSettings,
|
||||
IIdHelperService theIdHelper,
|
||||
IResourceLinkDao theResourceLinkDao) {
|
||||
IResourceLinkDao theResourceLinkDao,
|
||||
PartitionSettings thePartitionSettings) {
|
||||
return new DeleteExpungeSqlBuilder(
|
||||
theResourceTableFKProvider, theStorageSettings, theIdHelper, theResourceLinkDao);
|
||||
theResourceTableFKProvider, theStorageSettings, theIdHelper, theResourceLinkDao, thePartitionSettings);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,6 +57,10 @@ public class HapiFhirHibernateJpaDialect extends HibernateJpaDialect {
|
|||
if (theException.getCause() instanceof HibernateException) {
|
||||
return new PersistenceException(
|
||||
convertHibernateAccessException((HibernateException) theException.getCause(), theMessageToPrepend));
|
||||
} else if (theException instanceof HibernateException) {
|
||||
return new PersistenceException(
|
||||
theException.getMessage(),
|
||||
convertHibernateAccessException((HibernateException) theException, theMessageToPrepend));
|
||||
}
|
||||
return theException;
|
||||
}
|
||||
|
|
|
@ -729,7 +729,7 @@ public class JpaConfig {
|
|||
@Scope("prototype")
|
||||
public HistoryBuilder newHistoryBuilder(
|
||||
@Nullable String theResourceType,
|
||||
@Nullable Long theResourceId,
|
||||
@Nullable JpaPid theResourceId,
|
||||
@Nullable Date theRangeStartInclusive,
|
||||
@Nullable Date theRangeEndInclusive) {
|
||||
return new HistoryBuilder(theResourceType, theResourceId, theRangeStartInclusive, theRangeEndInclusive);
|
||||
|
|
|
@ -46,7 +46,6 @@ import ca.uhn.fhir.jpa.dao.index.DaoSearchParamSynchronizer;
|
|||
import ca.uhn.fhir.jpa.dao.index.SearchParamWithInlineReferencesExtractor;
|
||||
import ca.uhn.fhir.jpa.dao.tx.HapiTransactionService;
|
||||
import ca.uhn.fhir.jpa.delete.DeleteConflictService;
|
||||
import ca.uhn.fhir.jpa.entity.PartitionEntity;
|
||||
import ca.uhn.fhir.jpa.esr.ExternallyStoredResourceAddress;
|
||||
import ca.uhn.fhir.jpa.esr.ExternallyStoredResourceAddressMetadataKey;
|
||||
import ca.uhn.fhir.jpa.esr.ExternallyStoredResourceServiceRegistry;
|
||||
|
@ -559,8 +558,8 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> extends BaseStora
|
|||
} else {
|
||||
ResourceHistoryTable currentHistoryVersion = theEntity.getCurrentVersionEntity();
|
||||
if (currentHistoryVersion == null) {
|
||||
currentHistoryVersion =
|
||||
myResourceHistoryTableDao.findForIdAndVersion(theEntity.getId(), theEntity.getVersion());
|
||||
currentHistoryVersion = myResourceHistoryTableDao.findForIdAndVersion(
|
||||
theEntity.getId().toFk(), theEntity.getVersion());
|
||||
}
|
||||
if (currentHistoryVersion == null || !currentHistoryVersion.hasResource()) {
|
||||
changed = true;
|
||||
|
@ -914,9 +913,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> extends BaseStora
|
|||
// CREATE or UPDATE
|
||||
|
||||
IdentityHashMap<ResourceTable, ResourceIndexedSearchParams> existingSearchParams =
|
||||
theTransactionDetails.getOrCreateUserData(
|
||||
HapiTransactionService.XACT_USERDATA_KEY_EXISTING_SEARCH_PARAMS,
|
||||
() -> new IdentityHashMap<>());
|
||||
getSearchParamsMapFromTransaction(theTransactionDetails);
|
||||
existingParams = existingSearchParams.get(entity);
|
||||
if (existingParams == null) {
|
||||
existingParams = ResourceIndexedSearchParams.withLists(entity);
|
||||
|
@ -926,11 +923,11 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> extends BaseStora
|
|||
* old set later on
|
||||
*/
|
||||
if (existingParams.getResourceLinks().size() >= 10) {
|
||||
List<Long> pids = existingParams.getResourceLinks().stream()
|
||||
.map(t -> t.getId())
|
||||
List<Long> allPids = existingParams.getResourceLinks().stream()
|
||||
.map(ResourceLink::getId)
|
||||
.collect(Collectors.toList());
|
||||
new QueryChunker<Long>().chunk(pids, t -> {
|
||||
List<ResourceLink> targets = myResourceLinkDao.findByPidAndFetchTargetDetails(t);
|
||||
new QueryChunker<Long>().chunk(allPids, chunkPids -> {
|
||||
List<ResourceLink> targets = myResourceLinkDao.findByPidAndFetchTargetDetails(chunkPids);
|
||||
ourLog.trace("Prefetched targets: {}", targets);
|
||||
});
|
||||
}
|
||||
|
@ -952,8 +949,6 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> extends BaseStora
|
|||
requestPartitionId = RequestPartitionId.defaultPartition();
|
||||
}
|
||||
|
||||
failIfPartitionMismatch(theRequest, entity);
|
||||
|
||||
// Extract search params for resource
|
||||
mySearchParamWithInlineReferencesExtractor.populateFromResource(
|
||||
requestPartitionId,
|
||||
|
@ -1012,18 +1007,18 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> extends BaseStora
|
|||
return entity;
|
||||
}
|
||||
|
||||
if (entity.getId() != null && theUpdateVersion) {
|
||||
if (entity.getId().getId() != null && theUpdateVersion) {
|
||||
entity.markVersionUpdatedInCurrentTransaction();
|
||||
}
|
||||
|
||||
/*
|
||||
* Save the resource itself
|
||||
*/
|
||||
if (entity.getId() == null) {
|
||||
if (entity.getId().getId() == null) {
|
||||
myEntityManager.persist(entity);
|
||||
|
||||
if (entity.getFhirId() == null) {
|
||||
entity.setFhirId(Long.toString(entity.getResourceId()));
|
||||
entity.setFhirId(Long.toString(entity.getId().getId()));
|
||||
}
|
||||
|
||||
postPersist(entity, (T) theResource, theRequest);
|
||||
|
@ -1111,6 +1106,9 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> extends BaseStora
|
|||
compositeBroadcaster.callHooks(Pointcut.JPA_PERFTRACE_INFO, params);
|
||||
}
|
||||
}
|
||||
|
||||
// Put the final set of search params into the transaction
|
||||
getSearchParamsMapFromTransaction(theTransactionDetails).put(entity, newParams);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1121,6 +1119,12 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> extends BaseStora
|
|||
return entity;
|
||||
}
|
||||
|
||||
private static IdentityHashMap<ResourceTable, ResourceIndexedSearchParams> getSearchParamsMapFromTransaction(
|
||||
TransactionDetails theTransactionDetails) {
|
||||
return theTransactionDetails.getOrCreateUserData(
|
||||
HapiTransactionService.XACT_USERDATA_KEY_EXISTING_SEARCH_PARAMS, IdentityHashMap::new);
|
||||
}
|
||||
|
||||
/**
|
||||
* This methor returns the {@link EntityIndexStatusEnum} value that should be
|
||||
* used for a successfully fully indexed resource. This method will return
|
||||
|
@ -1183,11 +1187,11 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> extends BaseStora
|
|||
}
|
||||
}
|
||||
|
||||
public IBasePersistedResource updateHistoryEntity(
|
||||
public IBasePersistedResource<?> updateHistoryEntity(
|
||||
RequestDetails theRequest,
|
||||
T theResource,
|
||||
IBasePersistedResource theEntity,
|
||||
IBasePersistedResource theHistoryEntity,
|
||||
IBasePersistedResource<?> theEntity,
|
||||
IBasePersistedResource<?> theHistoryEntity,
|
||||
IIdType theResourceId,
|
||||
TransactionDetails theTransactionDetails,
|
||||
boolean isUpdatingCurrent) {
|
||||
|
@ -1291,29 +1295,6 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> extends BaseStora
|
|||
encodedResource.setEncoding(theEncoding);
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO eventually consider refactoring this to be part of an interceptor.
|
||||
* <p>
|
||||
* Throws an exception if the partition of the request, and the partition of the existing entity do not match.
|
||||
*
|
||||
* @param theRequest the request.
|
||||
* @param entity the existing entity.
|
||||
*/
|
||||
private void failIfPartitionMismatch(RequestDetails theRequest, ResourceTable entity) {
|
||||
if (myPartitionSettings.isPartitioningEnabled()
|
||||
&& theRequest != null
|
||||
&& theRequest.getTenantId() != null
|
||||
&& entity.getPartitionId() != null) {
|
||||
PartitionEntity partitionEntity = myPartitionLookupSvc.getPartitionByName(theRequest.getTenantId());
|
||||
// partitionEntity should never be null
|
||||
if (partitionEntity != null
|
||||
&& !partitionEntity.getId().equals(entity.getPartitionId().getPartitionId())) {
|
||||
throw new InvalidRequestException(Msg.code(2079) + "Resource " + entity.getResourceType() + "/"
|
||||
+ entity.getId() + " is not known");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void createHistoryEntry(
|
||||
RequestDetails theRequest, IBaseResource theResource, ResourceTable theEntity, EncodedResource theChanged) {
|
||||
boolean versionedTags =
|
||||
|
@ -1321,7 +1302,6 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> extends BaseStora
|
|||
|
||||
ResourceHistoryTable historyEntry = null;
|
||||
long resourceVersion = theEntity.getVersion();
|
||||
boolean reusingHistoryEntity = false;
|
||||
if (!myStorageSettings.isResourceDbHistoryEnabled() && resourceVersion > 1L) {
|
||||
/*
|
||||
* If we're not storing history, then just pull the current history
|
||||
|
@ -1329,10 +1309,9 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> extends BaseStora
|
|||
* this could return null if the current resourceVersion has been expunged
|
||||
* in which case we'll still create a new one
|
||||
*/
|
||||
historyEntry =
|
||||
myResourceHistoryTableDao.findForIdAndVersion(theEntity.getResourceId(), resourceVersion - 1);
|
||||
historyEntry = myResourceHistoryTableDao.findForIdAndVersion(
|
||||
theEntity.getResourceId().toFk(), resourceVersion - 1);
|
||||
if (historyEntry != null) {
|
||||
reusingHistoryEntity = true;
|
||||
theEntity.populateHistoryEntityVersionAndDates(historyEntry);
|
||||
if (versionedTags && theEntity.isHasTags()) {
|
||||
for (ResourceTag next : theEntity.getTags()) {
|
||||
|
@ -1543,9 +1522,9 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> extends BaseStora
|
|||
|
||||
protected void addPidToResource(IResourceLookup<JpaPid> theEntity, IBaseResource theResource) {
|
||||
if (theResource instanceof IAnyResource) {
|
||||
IDao.RESOURCE_PID.put(theResource, theEntity.getPersistentId().getId());
|
||||
IDao.RESOURCE_PID.put(theResource, theEntity.getPersistentId());
|
||||
} else if (theResource instanceof IResource) {
|
||||
IDao.RESOURCE_PID.put(theResource, theEntity.getPersistentId().getId());
|
||||
IDao.RESOURCE_PID.put(theResource, theEntity.getPersistentId());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -52,6 +52,8 @@ import ca.uhn.fhir.jpa.model.dao.JpaPid;
|
|||
import ca.uhn.fhir.jpa.model.entity.BaseHasResource;
|
||||
import ca.uhn.fhir.jpa.model.entity.BaseTag;
|
||||
import ca.uhn.fhir.jpa.model.entity.EntityIndexStatusEnum;
|
||||
import ca.uhn.fhir.jpa.model.entity.IBaseResourceEntity;
|
||||
import ca.uhn.fhir.jpa.model.entity.IdAndPartitionId;
|
||||
import ca.uhn.fhir.jpa.model.entity.PartitionablePartitionId;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceEncodingEnum;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceHistoryProvenanceEntity;
|
||||
|
@ -126,6 +128,7 @@ import jakarta.persistence.NoResultException;
|
|||
import jakarta.persistence.TypedQuery;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.apache.commons.lang3.function.TriFunction;
|
||||
import org.hl7.fhir.instance.model.api.IBaseCoding;
|
||||
import org.hl7.fhir.instance.model.api.IBaseMetaType;
|
||||
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
||||
|
@ -157,7 +160,6 @@ import java.util.Optional;
|
|||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
@ -421,6 +423,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
if (isNotBlank(theMatchUrl) && theProcessMatchUrl) {
|
||||
Set<JpaPid> match = myMatchResourceUrlService.processMatchUrl(
|
||||
theMatchUrl, myResourceType, theTransactionDetails, theRequest);
|
||||
ourLog.trace("Resolving match URL {} found: {}", theMatchUrl, match);
|
||||
if (match.size() > 1) {
|
||||
String msg = getContext()
|
||||
.getLocalizer()
|
||||
|
@ -472,7 +475,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
*/
|
||||
|
||||
Supplier<LazyDaoMethodOutcome.EntityAndResource> entitySupplier = () -> myTxTemplate.execute(tx -> {
|
||||
ResourceTable foundEntity = myEntityManager.find(ResourceTable.class, pid.getId());
|
||||
ResourceTable foundEntity = myEntityManager.find(ResourceTable.class, pid);
|
||||
IBaseResource resource = myJpaStorageResourceParser.toResource(foundEntity, false);
|
||||
theResource.setId(resource.getIdElement().getValue());
|
||||
return new LazyDaoMethodOutcome.EntityAndResource(foundEntity, resource);
|
||||
|
@ -483,7 +486,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
Long version = myMemoryCacheService.getIfPresent(
|
||||
MemoryCacheService.CacheEnum.RESOURCE_CONDITIONAL_CREATE_VERSION, pid.getId());
|
||||
if (version == null) {
|
||||
version = myResourceTableDao.findCurrentVersionByPid(pid.getId());
|
||||
version = myResourceTableDao.findCurrentVersionByPid(pid);
|
||||
if (version != null) {
|
||||
myMemoryCacheService.putAfterCommit(
|
||||
MemoryCacheService.CacheEnum.RESOURCE_CONDITIONAL_CREATE_VERSION,
|
||||
|
@ -733,10 +736,10 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
|
||||
final ResourceTable entity;
|
||||
try {
|
||||
entity = readEntityLatestVersion(theId, requestPartitionId, theTransactionDetails);
|
||||
entity = readEntityLatestVersion(theRequestDetails, theId, requestPartitionId, theTransactionDetails);
|
||||
} catch (ResourceNotFoundException ex) {
|
||||
// we don't want to throw 404s.
|
||||
// if not found, return an outcome anyways.
|
||||
// if not found, return an outcome anyway.
|
||||
// Because no object actually existed, we'll
|
||||
// just set the id and nothing else
|
||||
return createMethodOutcomeForResourceId(
|
||||
|
@ -750,7 +753,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
Msg.code(961) + "Trying to delete " + theId + " but this is not the current version");
|
||||
}
|
||||
|
||||
JpaPid persistentId = JpaPid.fromId(entity.getResourceId());
|
||||
JpaPid persistentId = entity.getId();
|
||||
theTransactionDetails.addDeletedResourceId(persistentId);
|
||||
|
||||
// Don't delete again if it's already deleted
|
||||
|
@ -941,7 +944,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
JpaPid jpaPid = (JpaPid) pid;
|
||||
|
||||
// This shouldn't actually need to hit the DB because we pre-fetch above
|
||||
ResourceTable entity = myEntityManager.find(ResourceTable.class, jpaPid.getId());
|
||||
ResourceTable entity = myEntityManager.find(ResourceTable.class, jpaPid);
|
||||
deletedResources.add(entity);
|
||||
|
||||
T resourceToDelete = myJpaStorageResourceParser.toResource(myResourceType, entity, null, false);
|
||||
|
@ -1040,7 +1043,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
|
||||
private <MT extends IBaseMetaType> void doMetaAdd(
|
||||
MT theMetaAdd,
|
||||
BaseHasResource theEntity,
|
||||
BaseHasResource<?> theEntity,
|
||||
RequestDetails theRequestDetails,
|
||||
TransactionDetails theTransactionDetails) {
|
||||
IBaseResource oldVersion = myJpaStorageResourceParser.toResource(theEntity, false);
|
||||
|
@ -1049,7 +1052,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
for (TagDefinition nextDef : tags) {
|
||||
|
||||
boolean entityHasTag = false;
|
||||
for (BaseTag next : new ArrayList<>(theEntity.getTags())) {
|
||||
for (BaseTag next : theEntity.getTags()) {
|
||||
if (Objects.equals(next.getTag().getTagType(), nextDef.getTagType())
|
||||
&& Objects.equals(next.getTag().getSystem(), nextDef.getSystem())
|
||||
&& Objects.equals(next.getTag().getCode(), nextDef.getCode())
|
||||
|
@ -1184,11 +1187,11 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
IIdType theId, ExpungeOptions theExpungeOptions, RequestDetails theRequest) {
|
||||
TransactionTemplate txTemplate = new TransactionTemplate(myPlatformTransactionManager);
|
||||
|
||||
BaseHasResource entity = txTemplate.execute(t -> readEntity(theId, theRequest));
|
||||
BaseHasResource<?> entity = txTemplate.execute(t -> readEntity(theId, theRequest));
|
||||
Validate.notNull(entity, "Resource with ID %s not found in database", theId);
|
||||
|
||||
if (theId.hasVersionIdPart()) {
|
||||
BaseHasResource currentVersion;
|
||||
BaseHasResource<?> currentVersion;
|
||||
currentVersion = txTemplate.execute(t -> readEntity(theId.toVersionless(), theRequest));
|
||||
Validate.notNull(
|
||||
currentVersion,
|
||||
|
@ -1201,15 +1204,15 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
+ theId.toUnqualified().getValue() + " as this is the current version");
|
||||
}
|
||||
|
||||
return myExpungeService.expunge(
|
||||
getResourceName(),
|
||||
JpaPid.fromIdAndVersion(entity.getResourceId(), entity.getVersion()),
|
||||
theExpungeOptions,
|
||||
theRequest);
|
||||
return myExpungeService.expunge(getResourceName(), entity.getResourceId(), theExpungeOptions, theRequest);
|
||||
}
|
||||
|
||||
return myExpungeService.expunge(
|
||||
getResourceName(), JpaPid.fromId(entity.getResourceId()), theExpungeOptions, theRequest);
|
||||
// Downstream code expects the version to be null in the JpaPid if we're not
|
||||
// doing a version specific expunge
|
||||
JpaPid resourceId = entity.getResourceId();
|
||||
resourceId = JpaPid.fromId(resourceId.getId(), resourceId.getPartitionId());
|
||||
|
||||
return myExpungeService.expunge(getResourceName(), resourceId, theExpungeOptions, theRequest);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1265,7 +1268,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
return myPersistedJpaBundleProviderFactory.history(
|
||||
theRequest,
|
||||
myResourceName,
|
||||
entity.getPersistentId(),
|
||||
entity.getResourceId(),
|
||||
theSince,
|
||||
theUntil,
|
||||
theOffset,
|
||||
|
@ -1295,7 +1298,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
return myPersistedJpaBundleProviderFactory.history(
|
||||
theRequest,
|
||||
myResourceName,
|
||||
JpaPid.fromId(entity.getId()),
|
||||
entity.getResourceId(),
|
||||
theHistorySearchDateRangeParam.getLowerBoundAsInstant(),
|
||||
theHistorySearchDateRangeParam.getUpperBoundAsInstant(),
|
||||
theHistorySearchDateRangeParam.getOffset(),
|
||||
|
@ -1388,15 +1391,16 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
throw new ResourceNotFoundException(Msg.code(1993) + theResourceId);
|
||||
}
|
||||
|
||||
ResourceTable latestVersion = readEntityLatestVersion(theResourceId, theRequestPartitionId, transactionDetails);
|
||||
ResourceTable latestVersion =
|
||||
readEntityLatestVersion(theRequest, theResourceId, theRequestPartitionId, transactionDetails);
|
||||
if (latestVersion.getVersion() != entity.getVersion()) {
|
||||
doMetaAdd(theMetaAdd, entity, theRequest, transactionDetails);
|
||||
} else {
|
||||
doMetaAdd(theMetaAdd, latestVersion, theRequest, transactionDetails);
|
||||
|
||||
// Also update history entry
|
||||
ResourceHistoryTable history =
|
||||
myResourceHistoryTableDao.findForIdAndVersion(entity.getId(), entity.getVersion());
|
||||
ResourceHistoryTable history = myResourceHistoryTableDao.findForIdAndVersion(
|
||||
entity.getResourceId().toFk(), entity.getVersion());
|
||||
doMetaAdd(theMetaAdd, history, theRequest, transactionDetails);
|
||||
}
|
||||
|
||||
|
@ -1434,7 +1438,8 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
throw new ResourceNotFoundException(Msg.code(1994) + theResourceId);
|
||||
}
|
||||
|
||||
ResourceTable latestVersion = readEntityLatestVersion(theResourceId, theRequestPartitionId, transactionDetails);
|
||||
ResourceTable latestVersion =
|
||||
readEntityLatestVersion(theRequest, theResourceId, theRequestPartitionId, transactionDetails);
|
||||
boolean nonVersionedTags =
|
||||
myStorageSettings.getTagStorageMode() != JpaStorageSettings.TagStorageModeEnum.VERSIONED;
|
||||
|
||||
|
@ -1443,8 +1448,8 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
} else {
|
||||
doMetaDelete(theMetaDel, latestVersion, theRequest, transactionDetails);
|
||||
// Also update history entry
|
||||
ResourceHistoryTable history =
|
||||
myResourceHistoryTableDao.findForIdAndVersion(entity.getId(), entity.getVersion());
|
||||
ResourceHistoryTable history = myResourceHistoryTableDao.findForIdAndVersion(
|
||||
entity.getResourceId().toFk(), entity.getVersion());
|
||||
doMetaDelete(theMetaDel, history, theRequest, transactionDetails);
|
||||
}
|
||||
|
||||
|
@ -1455,7 +1460,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
public <MT extends IBaseMetaType> MT metaGetOperation(Class<MT> theType, IIdType theId, RequestDetails theRequest) {
|
||||
return myTransactionService.withRequest(theRequest).execute(() -> {
|
||||
Set<TagDefinition> tagDefs = new HashSet<>();
|
||||
BaseHasResource entity = readEntity(theId, theRequest);
|
||||
BaseHasResource<?> entity = readEntity(theId, theRequest);
|
||||
for (BaseTag next : entity.getTags()) {
|
||||
tagDefs.add(next.getTag());
|
||||
}
|
||||
|
@ -1522,7 +1527,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
StopWatch w = new StopWatch();
|
||||
JpaPid jpaPid = (JpaPid) thePid;
|
||||
|
||||
Optional<ResourceTable> entity = myResourceTableDao.findById(jpaPid.getId());
|
||||
Optional<ResourceTable> entity = myResourceTableDao.findById(jpaPid);
|
||||
if (entity.isEmpty()) {
|
||||
throw new ResourceNotFoundException(Msg.code(975) + "No resource found with PID " + jpaPid);
|
||||
}
|
||||
|
@ -1569,10 +1574,11 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
assert TransactionSynchronizationManager.isActualTransactionActive();
|
||||
|
||||
StopWatch w = new StopWatch();
|
||||
BaseHasResource entity = readEntity(theId, true, theRequest, theRequestPartitionId);
|
||||
BaseHasResource<?> entity = readEntity(theId, true, theRequest, theRequestPartitionId);
|
||||
validateResourceType(entity);
|
||||
|
||||
T retVal = myJpaStorageResourceParser.toResource(myResourceType, entity, null, false);
|
||||
T retVal = myJpaStorageResourceParser.toResource(
|
||||
myResourceType, (IBaseResourceEntity<JpaPid>) entity, null, false);
|
||||
|
||||
if (!theDeletedOk) {
|
||||
if (isDeleted(entity)) {
|
||||
|
@ -1642,9 +1648,9 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
// We use the main entity as the lock object since all the index rows hang off it.
|
||||
ResourceTable entity;
|
||||
if (theReindexParameters.isOptimisticLock()) {
|
||||
entity = myEntityManager.find(ResourceTable.class, jpaPid.getId(), LockModeType.OPTIMISTIC);
|
||||
entity = myEntityManager.find(ResourceTable.class, jpaPid, LockModeType.OPTIMISTIC);
|
||||
} else {
|
||||
entity = myEntityManager.find(ResourceTable.class, jpaPid.getId());
|
||||
entity = myEntityManager.find(ResourceTable.class, jpaPid);
|
||||
}
|
||||
|
||||
if (entity == null) {
|
||||
|
@ -1709,7 +1715,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
ResourceTable entity, ReindexParameters.OptimizeStorageModeEnum theOptimizeStorageMode) {
|
||||
ResourceHistoryTable historyEntity = entity.getCurrentVersionEntity();
|
||||
if (historyEntity != null) {
|
||||
reindexOptimizeStorageHistoryEntityThenDetachIt(entity, historyEntity);
|
||||
reindexOptimizeStorageHistoryEntity(entity, historyEntity);
|
||||
if (theOptimizeStorageMode == ReindexParameters.OptimizeStorageModeEnum.ALL_VERSIONS) {
|
||||
int pageSize = 100;
|
||||
for (int page = 0; ((long) page * pageSize) < entity.getVersion(); page++) {
|
||||
|
@ -1720,10 +1726,10 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
PageRequest pageRequest = PageRequest.of(page, pageSize, Sort.by("myId"));
|
||||
Slice<ResourceHistoryTable> historyEntities =
|
||||
myResourceHistoryTableDao.findAllVersionsExceptSpecificForResourcePid(
|
||||
pageRequest, entity.getId(), historyEntity.getVersion());
|
||||
pageRequest, entity.getId().toFk(), historyEntity.getVersion());
|
||||
|
||||
for (ResourceHistoryTable next : historyEntities) {
|
||||
reindexOptimizeStorageHistoryEntityThenDetachIt(entity, next);
|
||||
reindexOptimizeStorageHistoryEntity(entity, next);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1734,8 +1740,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
* Note that the entity will be detached after being saved if it has changed
|
||||
* in order to avoid growing the number of resources in memory to be too big
|
||||
*/
|
||||
private void reindexOptimizeStorageHistoryEntityThenDetachIt(
|
||||
ResourceTable entity, ResourceHistoryTable historyEntity) {
|
||||
private void reindexOptimizeStorageHistoryEntity(ResourceTable entity, ResourceHistoryTable historyEntity) {
|
||||
if (historyEntity.getEncoding() == ResourceEncodingEnum.JSONC
|
||||
|| historyEntity.getEncoding() == ResourceEncodingEnum.JSON) {
|
||||
byte[] resourceBytes = historyEntity.getResource();
|
||||
|
@ -1746,7 +1751,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
}
|
||||
if (myStorageSettings.isAccessMetaSourceInformationFromProvenanceTable()) {
|
||||
if (isBlank(historyEntity.getSourceUri()) && isBlank(historyEntity.getRequestId())) {
|
||||
Long id = historyEntity.getId();
|
||||
IdAndPartitionId id = historyEntity.getId().asIdAndPartitionId();
|
||||
Optional<ResourceHistoryProvenanceEntity> provenanceEntityOpt =
|
||||
myResourceHistoryProvenanceDao.findById(id);
|
||||
if (provenanceEntityOpt.isPresent()) {
|
||||
|
@ -1759,7 +1764,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
}
|
||||
}
|
||||
|
||||
private BaseHasResource readEntity(
|
||||
private BaseHasResource<?> readEntity(
|
||||
IIdType theId,
|
||||
boolean theCheckForForcedId,
|
||||
RequestDetails theRequest,
|
||||
|
@ -1776,7 +1781,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
.getPersistentId();
|
||||
Set<Integer> readPartitions = null;
|
||||
if (requestPartitionId.isAllPartitions()) {
|
||||
entity = myEntityManager.find(ResourceTable.class, pid.getId());
|
||||
entity = myEntityManager.find(ResourceTable.class, pid);
|
||||
} else {
|
||||
readPartitions = myRequestPartitionHelperService.toReadPartitions(requestPartitionId);
|
||||
if (readPartitions.size() == 1) {
|
||||
|
@ -1872,7 +1877,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
RequestDetails theRequestDetails,
|
||||
TransactionDetails theTransactionDetails) {
|
||||
JpaPid jpaPid = (JpaPid) thePersistentId;
|
||||
return myEntityManager.find(ResourceTable.class, jpaPid.getId());
|
||||
return myEntityManager.find(ResourceTable.class, jpaPid);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1885,11 +1890,13 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
return myTransactionService
|
||||
.withRequest(theRequestDetails)
|
||||
.withRequestPartitionId(requestPartitionId)
|
||||
.execute(() -> readEntityLatestVersion(theId, requestPartitionId, theTransactionDetails));
|
||||
.execute(() ->
|
||||
readEntityLatestVersion(theRequestDetails, theId, requestPartitionId, theTransactionDetails));
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private ResourceTable readEntityLatestVersion(
|
||||
RequestDetails theRequestDetails,
|
||||
IIdType theId,
|
||||
@Nonnull RequestPartitionId theRequestPartitionId,
|
||||
TransactionDetails theTransactionDetails) {
|
||||
|
@ -1919,7 +1926,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
ResolveIdentityMode.includeDeleted().cacheOk());
|
||||
}
|
||||
|
||||
ResourceTable entity = myEntityManager.find(ResourceTable.class, persistentId.getId());
|
||||
ResourceTable entity = myEntityManager.find(ResourceTable.class, persistentId);
|
||||
if (entity == null) {
|
||||
throw new ResourceNotFoundException(Msg.code(1998) + id);
|
||||
}
|
||||
|
@ -1938,7 +1945,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
public void removeTag(
|
||||
IIdType theId, TagTypeEnum theTagType, String theScheme, String theTerm, RequestDetails theRequest) {
|
||||
StopWatch w = new StopWatch();
|
||||
BaseHasResource entity = readEntity(theId, theRequest);
|
||||
BaseHasResource<?> entity = readEntity(theId, theRequest);
|
||||
if (entity == null) {
|
||||
throw new ResourceNotFoundException(Msg.code(1999) + theId);
|
||||
}
|
||||
|
@ -2171,7 +2178,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
private <V> List<V> searchForTransformedIds(
|
||||
SearchParameterMap theParams,
|
||||
RequestDetails theRequest,
|
||||
BiFunction<RequestDetails, Stream<JpaPid>, Stream<V>> transform) {
|
||||
TriFunction<RequestDetails, Stream<JpaPid>, RequestPartitionId, Stream<V>> transform) {
|
||||
RequestPartitionId requestPartitionId =
|
||||
myRequestPartitionHelperService.determineReadPartitionForRequestForSearchType(
|
||||
theRequest, myResourceName, theParams);
|
||||
|
@ -2188,7 +2195,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
Stream<JpaPid> pidStream =
|
||||
builder.createQueryStream(theParams, searchRuntimeDetails, theRequest, requestPartitionId);
|
||||
|
||||
Stream<V> transformedStream = transform.apply(theRequest, pidStream);
|
||||
Stream<V> transformedStream = transform.apply(theRequest, pidStream, requestPartitionId);
|
||||
|
||||
return transformedStream.collect(Collectors.toList());
|
||||
});
|
||||
|
@ -2198,12 +2205,13 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
* Fetch the resources in chunks and apply PreAccess/PreShow interceptors.
|
||||
*/
|
||||
@Nonnull
|
||||
private Stream<T> pidsToResource(RequestDetails theRequest, Stream<JpaPid> pidStream) {
|
||||
private Stream<T> pidsToResource(
|
||||
RequestDetails theRequest, Stream<JpaPid> thePidStream, RequestPartitionId theRequestPartitionId) {
|
||||
ISearchBuilder<JpaPid> searchBuilder =
|
||||
mySearchBuilderFactory.newSearchBuilder(getResourceName(), getResourceType());
|
||||
@SuppressWarnings("unchecked")
|
||||
Stream<T> resourceStream = (Stream<T>) new QueryChunker<>()
|
||||
.chunk(pidStream, SearchBuilder.getMaximumPageSize())
|
||||
.chunk(thePidStream, SearchBuilder.getMaximumPageSize())
|
||||
.flatMap(pidChunk -> searchBuilder.loadResourcesByPid(pidChunk, theRequest).stream());
|
||||
// apply interceptors
|
||||
return resourceStream
|
||||
|
@ -2215,11 +2223,19 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
* get the Ids from the ResourceTable entities in chunks.
|
||||
*/
|
||||
@Nonnull
|
||||
private Stream<IIdType> pidsToIds(RequestDetails theRequestDetails, Stream<JpaPid> thePidStream) {
|
||||
Stream<Long> longStream = thePidStream.map(JpaPid::getId);
|
||||
private Stream<IIdType> pidsToIds(
|
||||
RequestDetails theRequestDetails, Stream<JpaPid> thePidStream, RequestPartitionId theRequestPartitionId) {
|
||||
|
||||
Stream<JpaPid> pidStream = thePidStream;
|
||||
|
||||
if (!theRequestPartitionId.isAllPartitions()
|
||||
&& theRequestPartitionId.getPartitionIds().size() == 1) {
|
||||
pidStream = pidStream.map(t -> t.setPartitionIdIfNotAlreadySet(
|
||||
theRequestPartitionId.getPartitionIds().get(0)));
|
||||
}
|
||||
|
||||
return new QueryChunker<>()
|
||||
.chunk(longStream, SearchBuilder.getMaximumPageSize())
|
||||
.chunk(pidStream, SearchBuilder.getMaximumPageSize())
|
||||
.flatMap(ids -> myResourceTableDao.findAllById(ids).stream())
|
||||
.map(ResourceTable::getIdDt);
|
||||
}
|
||||
|
@ -2386,7 +2402,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
throw new PreconditionFailedException(Msg.code(988) + msg);
|
||||
} else if (match.size() == 1) {
|
||||
JpaPid pid = match.iterator().next();
|
||||
entity = myEntityManager.find(ResourceTable.class, pid.getId());
|
||||
entity = myEntityManager.find(ResourceTable.class, pid);
|
||||
resourceId = entity.getIdDt();
|
||||
if (myFhirContext.getVersion().getVersion().isEqualOrNewerThan(FhirVersionEnum.R4)
|
||||
&& theResource.getIdElement().getIdPart() != null) {
|
||||
|
@ -2450,7 +2466,8 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
|
||||
if (!create) {
|
||||
try {
|
||||
entity = readEntityLatestVersion(resourceId, theRequestPartitionId, theTransactionDetails);
|
||||
entity = readEntityLatestVersion(
|
||||
theRequest, resourceId, theRequestPartitionId, theTransactionDetails);
|
||||
} catch (ResourceNotFoundException e) {
|
||||
create = true;
|
||||
}
|
||||
|
@ -2494,8 +2511,8 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
if (!theTransactionDetails.isFhirTransaction()) {
|
||||
Set<IResourcePersistentId> resourceIds = theTransactionDetails.getUpdatedResourceIds();
|
||||
if (resourceIds != null && !resourceIds.isEmpty()) {
|
||||
List<Long> ids = resourceIds.stream().map(r -> (Long) r.getId()).collect(Collectors.toList());
|
||||
|
||||
@Nonnull
|
||||
List<JpaPid> ids = resourceIds.stream().map(r -> (JpaPid) r).collect(Collectors.toList());
|
||||
myResourceSearchUrlSvc.deleteByResIds(ids);
|
||||
}
|
||||
}
|
||||
|
@ -2519,8 +2536,21 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
* duplicate index violations if we try to add another (after this create/update)
|
||||
*/
|
||||
ResourceTable entity = (ResourceTable) theEntity;
|
||||
|
||||
/*
|
||||
* If we read back the entity from hibernate, and it's already saying
|
||||
* it's been updated in this transaction, then someone is probably
|
||||
* doing multiple modifications of the same resource within the same
|
||||
* database transaction. The only way for this to work cleanly is for
|
||||
* us to flush hibernate now. That way we can increment the version
|
||||
* a second time, create multiple history entries, etc.
|
||||
*/
|
||||
if (entity != null && entity.isVersionUpdatedInCurrentTransaction()) {
|
||||
myEntityManager.flush();
|
||||
}
|
||||
|
||||
if (entity.isSearchUrlPresent()) {
|
||||
JpaPid persistentId = JpaPid.fromId(entity.getResourceId());
|
||||
JpaPid persistentId = entity.getResourceId();
|
||||
theTransactionDetails.addUpdatedResourceId(persistentId);
|
||||
|
||||
entity.setSearchUrlPresent(false); // it will be removed at the end
|
||||
|
@ -2578,8 +2608,8 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
assert resourceId.hasIdPart();
|
||||
|
||||
try {
|
||||
currentEntity =
|
||||
readEntityLatestVersion(resourceId.toVersionless(), theRequestPartitionId, theTransactionDetails);
|
||||
currentEntity = readEntityLatestVersion(
|
||||
theRequest, resourceId.toVersionless(), theRequestPartitionId, theTransactionDetails);
|
||||
|
||||
if (!resourceId.hasVersionIdPart()) {
|
||||
throw new InvalidRequestException(
|
||||
|
@ -2640,7 +2670,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
.withRequestPartitionId(requestPartitionId)
|
||||
.execute(() -> {
|
||||
final ResourceTable entity =
|
||||
readEntityLatestVersion(theId, requestPartitionId, transactionDetails);
|
||||
readEntityLatestVersion(theRequest, theId, requestPartitionId, transactionDetails);
|
||||
|
||||
// Validate that there are no resources pointing to the candidate that
|
||||
// would prevent deletion
|
||||
|
@ -2723,7 +2753,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
}
|
||||
}
|
||||
|
||||
private void validateResourceType(BaseHasResource entity) {
|
||||
private void validateResourceType(IBasePersistedResource<?> entity) {
|
||||
validateResourceType(entity, myResourceName);
|
||||
}
|
||||
|
||||
|
|
|
@ -190,7 +190,7 @@ public abstract class BaseHapiFhirSystemDao<T extends IBaseBundle, MT> extends B
|
|||
public <P extends IResourcePersistentId> void preFetchResources(
|
||||
List<P> theResolvedIds, boolean thePreFetchIndexes) {
|
||||
HapiTransactionService.requireTransaction();
|
||||
List<Long> pids = theResolvedIds.stream().map(t -> ((JpaPid) t).getId()).collect(Collectors.toList());
|
||||
List<JpaPid> pids = theResolvedIds.stream().map(t -> ((JpaPid) t)).collect(Collectors.toList());
|
||||
|
||||
QueryChunker.chunk(pids, idChunk -> {
|
||||
|
||||
|
@ -215,7 +215,13 @@ public abstract class BaseHapiFhirSystemDao<T extends IBaseBundle, MT> extends B
|
|||
prefetchByField("date", "myParamsDate", ResourceTable::isParamsDatePopulated, entityChunk);
|
||||
prefetchByField(
|
||||
"quantity", "myParamsQuantity", ResourceTable::isParamsQuantityPopulated, entityChunk);
|
||||
prefetchByField("resourceLinks", "myResourceLinks", ResourceTable::isHasLinks, entityChunk);
|
||||
|
||||
prefetchByJoinClause(
|
||||
"resourceLinks",
|
||||
// fetch the ResourceLink but also the target resource for that link
|
||||
"LEFT JOIN FETCH r.myResourceLinks l LEFT JOIN FETCH l.myTargetResource",
|
||||
ResourceTable::isHasLinks,
|
||||
entityChunk);
|
||||
|
||||
prefetchByJoinClause(
|
||||
"tags",
|
||||
|
@ -244,14 +250,14 @@ public abstract class BaseHapiFhirSystemDao<T extends IBaseBundle, MT> extends B
|
|||
}
|
||||
|
||||
@Nonnull
|
||||
private List<ResourceTable> prefetchResourceTableAndHistory(List<Long> idChunk) {
|
||||
private List<ResourceTable> prefetchResourceTableAndHistory(List<JpaPid> idChunk) {
|
||||
assert idChunk.size() < SearchConstants.MAX_PAGE_SIZE : "assume pre-chunked";
|
||||
|
||||
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 "
|
||||
+ " WHERE r.myId IN ( :IDS ) ");
|
||||
+ " on r.myVersion = h.myResourceVersion and r = h.myResourceTable "
|
||||
+ " WHERE r.myPid IN ( :IDS ) ");
|
||||
query.setParameter("IDS", idChunk);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
@ -302,7 +308,7 @@ public abstract class BaseHapiFhirSystemDao<T extends IBaseBundle, MT> extends B
|
|||
List<ResourceTable> theEntities) {
|
||||
|
||||
// Which entities need this prefetch?
|
||||
List<Long> idSubset = theEntities.stream()
|
||||
List<JpaPid> idSubset = theEntities.stream()
|
||||
.filter(theEntityPredicate)
|
||||
.map(ResourceTable::getId)
|
||||
.collect(Collectors.toList());
|
||||
|
@ -312,7 +318,7 @@ public abstract class BaseHapiFhirSystemDao<T extends IBaseBundle, MT> extends B
|
|||
return;
|
||||
}
|
||||
|
||||
String jqlQuery = "FROM ResourceTable r " + theJoinClause + " WHERE r.myId IN ( :IDS )";
|
||||
String jqlQuery = "FROM ResourceTable r " + theJoinClause + " WHERE r.myPid IN ( :IDS )";
|
||||
|
||||
TypedQuery<ResourceTable> query = myEntityManager.createQuery(jqlQuery, ResourceTable.class);
|
||||
query.setParameter("IDS", idSubset);
|
||||
|
|
|
@ -43,32 +43,18 @@ public class FhirResourceDaoSubscriptionDstu2 extends BaseHapiFhirResourceDao<Su
|
|||
@Autowired
|
||||
private PlatformTransactionManager myTxManager;
|
||||
|
||||
private void createSubscriptionTable(ResourceTable theEntity, Subscription theSubscription) {
|
||||
SubscriptionTable subscriptionEntity = new SubscriptionTable();
|
||||
subscriptionEntity.setCreated(new Date());
|
||||
subscriptionEntity.setSubscriptionResource(theEntity);
|
||||
myEntityManager.persist(subscriptionEntity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getSubscriptionTablePidForSubscriptionResource(
|
||||
IIdType theId, RequestDetails theRequest, TransactionDetails theTransactionDetails) {
|
||||
ResourceTable entity = readEntityLatestVersion(theId, theRequest, theTransactionDetails);
|
||||
SubscriptionTable table = mySubscriptionTableDao.findOneByResourcePid(entity.getId());
|
||||
SubscriptionTable table =
|
||||
mySubscriptionTableDao.findOneByResourcePid(entity.getId().getId());
|
||||
if (table == null) {
|
||||
return null;
|
||||
}
|
||||
return table.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void postPersist(
|
||||
ResourceTable theEntity, Subscription theSubscription, RequestDetails theRequestDetails) {
|
||||
super.postPersist(theEntity, theSubscription, theRequestDetails);
|
||||
|
||||
createSubscriptionTable(theEntity, theSubscription);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceTable updateEntity(
|
||||
RequestDetails theRequest,
|
||||
|
@ -92,7 +78,8 @@ public class FhirResourceDaoSubscriptionDstu2 extends BaseHapiFhirResourceDao<Su
|
|||
theCreateNewHistoryEntry);
|
||||
|
||||
if (theDeletedTimestampOrNull != null) {
|
||||
mySubscriptionTableDao.deleteAllForSubscription((ResourceTable) theEntity);
|
||||
mySubscriptionTableDao.deleteAllForSubscription(
|
||||
((ResourceTable) theEntity).getResourceId().getId());
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
|
|
@ -193,7 +193,7 @@ public class FulltextSearchSvcImpl implements IFulltextSearchSvc {
|
|||
String theResourceType, SearchParameterMap theParams, RequestDetails theRequestDetails) {
|
||||
validateHibernateSearchIsEnabled();
|
||||
|
||||
SearchQueryOptionsStep<?, Long, SearchLoadingOptionsStep, ?, ?> searchQueryOptionsStep =
|
||||
SearchQueryOptionsStep<?, JpaPid, SearchLoadingOptionsStep, ?, ?> searchQueryOptionsStep =
|
||||
getSearchQueryOptionsStep(theResourceType, theParams, null);
|
||||
logQuery(searchQueryOptionsStep, theRequestDetails);
|
||||
|
||||
|
@ -213,14 +213,14 @@ public class FulltextSearchSvcImpl implements IFulltextSearchSvc {
|
|||
int count = getMaxFetchSize(theParams, theMaxResultsToFetch);
|
||||
|
||||
// perform an offset search instead of a scroll one, which doesn't allow for offset
|
||||
SearchQueryOptionsStep<?, Long, SearchLoadingOptionsStep, ?, ?> searchQueryOptionsStep =
|
||||
SearchQueryOptionsStep<?, JpaPid, SearchLoadingOptionsStep, ?, ?> searchQueryOptionsStep =
|
||||
getSearchQueryOptionsStep(theResourceType, theParams, theReferencingPid);
|
||||
logQuery(searchQueryOptionsStep, theRequestDetails);
|
||||
List<Long> longs = searchQueryOptionsStep.fetchHits(offset, count);
|
||||
List<JpaPid> longs = searchQueryOptionsStep.fetchHits(offset, count);
|
||||
|
||||
// indicate param was already processed, otherwise queries DB to process it
|
||||
theParams.setOffset(null);
|
||||
return SearchQueryExecutors.from(JpaPid.fromLongList(longs));
|
||||
return SearchQueryExecutors.from(longs);
|
||||
}
|
||||
|
||||
private int getMaxFetchSize(SearchParameterMap theParams, Integer theMax) {
|
||||
|
@ -237,16 +237,16 @@ public class FulltextSearchSvcImpl implements IFulltextSearchSvc {
|
|||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
private SearchQueryOptionsStep<?, Long, SearchLoadingOptionsStep, ?, ?> getSearchQueryOptionsStep(
|
||||
private SearchQueryOptionsStep<?, JpaPid, SearchLoadingOptionsStep, ?, ?> getSearchQueryOptionsStep(
|
||||
String theResourceType, SearchParameterMap theParams, IResourcePersistentId theReferencingPid) {
|
||||
|
||||
dispatchEvent(IHSearchEventListener.HSearchEventType.SEARCH);
|
||||
var query = getSearchSession()
|
||||
SearchQueryOptionsStep<?, JpaPid, SearchLoadingOptionsStep, ?, ?> query = getSearchSession()
|
||||
.search(ResourceTable.class)
|
||||
// The document id is the PK which is pid. We use this instead of _myId to avoid fetching the doc body.
|
||||
.select(
|
||||
// adapt the String docRef.id() to the Long that it really is.
|
||||
f -> f.composite(docRef -> Long.valueOf(docRef.id()), f.documentReference()))
|
||||
f -> f.composite(docRef -> JpaPid.fromId(Long.valueOf(docRef.id())), f.documentReference()))
|
||||
.where(f -> buildWhereClause(f, theResourceType, theParams, theReferencingPid));
|
||||
|
||||
if (theParams.getSort() != null) {
|
||||
|
@ -456,7 +456,7 @@ public class FulltextSearchSvcImpl implements IFulltextSearchSvc {
|
|||
List<ExtendedHSearchResourceProjection> rawResourceDataList = session.search(ResourceTable.class)
|
||||
.select(this::buildResourceSelectClause)
|
||||
.where(
|
||||
f -> f.id().matchingAny(thePids) // matches '_id' from resource index
|
||||
f -> f.id().matchingAny(JpaPid.fromLongList(thePids)) // matches '_id' from resource index
|
||||
)
|
||||
.fetchAllHits();
|
||||
|
||||
|
@ -480,14 +480,14 @@ public class FulltextSearchSvcImpl implements IFulltextSearchSvc {
|
|||
SearchProjectionFactory<EntityReference, ResourceTable> f) {
|
||||
return f.composite(
|
||||
ExtendedHSearchResourceProjection::new,
|
||||
f.field("myId", Long.class),
|
||||
f.field("myId", JpaPid.class),
|
||||
f.field("myForcedId", String.class),
|
||||
f.field("myRawResource", String.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public long count(String theResourceName, SearchParameterMap theParams) {
|
||||
SearchQueryOptionsStep<?, Long, SearchLoadingOptionsStep, ?, ?> queryOptionsStep =
|
||||
SearchQueryOptionsStep<?, JpaPid, SearchLoadingOptionsStep, ?, ?> queryOptionsStep =
|
||||
getSearchQueryOptionsStep(theResourceName, theParams, null);
|
||||
|
||||
return queryOptionsStep.fetchTotalHitCount();
|
||||
|
|
|
@ -55,7 +55,6 @@ import java.util.Date;
|
|||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static ca.uhn.fhir.jpa.util.QueryParameterUtils.toPredicateArray;
|
||||
|
||||
|
@ -66,7 +65,7 @@ public class HistoryBuilder {
|
|||
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(HistoryBuilder.class);
|
||||
private final String myResourceType;
|
||||
private final Long myResourceId;
|
||||
private final JpaPid myResourceId;
|
||||
private final Date myRangeStartInclusive;
|
||||
private final Date myRangeEndInclusive;
|
||||
|
||||
|
@ -90,7 +89,7 @@ public class HistoryBuilder {
|
|||
*/
|
||||
public HistoryBuilder(
|
||||
@Nullable String theResourceType,
|
||||
@Nullable Long theResourceId,
|
||||
@Nullable JpaPid theResourceId,
|
||||
@Nullable Date theRangeStartInclusive,
|
||||
@Nullable Date theRangeEndInclusive) {
|
||||
myResourceType = theResourceType;
|
||||
|
@ -111,7 +110,6 @@ public class HistoryBuilder {
|
|||
return query.getSingleResult();
|
||||
}
|
||||
|
||||
@SuppressWarnings("OptionalIsPresent")
|
||||
public List<ResourceHistoryTable> fetchEntities(
|
||||
RequestPartitionId thePartitionId,
|
||||
Integer theOffset,
|
||||
|
@ -151,20 +149,18 @@ public class HistoryBuilder {
|
|||
|
||||
List<ResourceHistoryTable> tables = query.getResultList();
|
||||
if (!tables.isEmpty()) {
|
||||
ImmutableListMultimap<Long, ResourceHistoryTable> resourceIdToHistoryEntries =
|
||||
ImmutableListMultimap<JpaPid, ResourceHistoryTable> resourceIdToHistoryEntries =
|
||||
Multimaps.index(tables, ResourceHistoryTable::getResourceId);
|
||||
Set<JpaPid> pids = resourceIdToHistoryEntries.keySet().stream()
|
||||
.map(JpaPid::fromId)
|
||||
.collect(Collectors.toSet());
|
||||
Set<JpaPid> pids = resourceIdToHistoryEntries.keySet();
|
||||
PersistentIdToForcedIdMap<JpaPid> pidToForcedId = myIdHelperService.translatePidsToForcedIds(pids);
|
||||
ourLog.trace("Translated IDs: {}", pidToForcedId.getResourcePersistentIdOptionalMap());
|
||||
|
||||
for (Long nextResourceId : resourceIdToHistoryEntries.keySet()) {
|
||||
for (JpaPid nextResourceId : resourceIdToHistoryEntries.keySet()) {
|
||||
List<ResourceHistoryTable> historyTables = resourceIdToHistoryEntries.get(nextResourceId);
|
||||
|
||||
String resourceId;
|
||||
|
||||
Optional<String> forcedId = pidToForcedId.get(JpaPid.fromId(nextResourceId));
|
||||
Optional<String> forcedId = pidToForcedId.get(nextResourceId);
|
||||
if (forcedId.isPresent()) {
|
||||
resourceId = forcedId.get();
|
||||
// IdHelperService returns a forcedId with the '<resourceType>/' prefix
|
||||
|
@ -177,7 +173,7 @@ public class HistoryBuilder {
|
|||
resourceId = resourceId.substring(slashIdx + 1);
|
||||
}
|
||||
} else {
|
||||
resourceId = nextResourceId.toString();
|
||||
resourceId = Long.toString(nextResourceId.getId());
|
||||
}
|
||||
|
||||
for (ResourceHistoryTable nextHistoryTable : historyTables) {
|
||||
|
@ -197,25 +193,38 @@ public class HistoryBuilder {
|
|||
HistorySearchStyleEnum theHistorySearchStyle) {
|
||||
List<Predicate> predicates = new ArrayList<>();
|
||||
|
||||
if (!thePartitionId.isAllPartitions()) {
|
||||
if (thePartitionId.isDefaultPartition()) {
|
||||
predicates.add(theCriteriaBuilder.isNull(theFrom.get("myPartitionIdValue")));
|
||||
} else if (thePartitionId.hasDefaultPartitionId()) {
|
||||
predicates.add(theCriteriaBuilder.or(
|
||||
theCriteriaBuilder.isNull(theFrom.get("myPartitionIdValue")),
|
||||
theFrom.get("myPartitionIdValue").in(thePartitionId.getPartitionIdsWithoutDefault())));
|
||||
} else {
|
||||
predicates.add(theFrom.get("myPartitionIdValue").in(thePartitionId.getPartitionIds()));
|
||||
}
|
||||
}
|
||||
|
||||
if (myResourceId != null) {
|
||||
predicates.add(theCriteriaBuilder.equal(theFrom.get("myResourceId"), myResourceId));
|
||||
} else if (myResourceType != null) {
|
||||
validateNotSearchingAllPartitions(thePartitionId);
|
||||
predicates.add(theCriteriaBuilder.equal(theFrom.get("myResourceType"), myResourceType));
|
||||
|
||||
predicates.add(theCriteriaBuilder.equal(theFrom.get("myResourceId"), myResourceId.getId()));
|
||||
if (myPartitionSettings.isPartitioningEnabled()) {
|
||||
if (myResourceId.getPartitionId() != null) {
|
||||
predicates.add(
|
||||
theCriteriaBuilder.equal(theFrom.get("myPartitionIdValue"), myResourceId.getPartitionId()));
|
||||
} else {
|
||||
predicates.add(theCriteriaBuilder.isNull(theFrom.get("myPartitionIdValue")));
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
validateNotSearchingAllPartitions(thePartitionId);
|
||||
|
||||
if (!thePartitionId.isAllPartitions()) {
|
||||
if (thePartitionId.isDefaultPartition()) {
|
||||
predicates.add(theCriteriaBuilder.isNull(theFrom.get("myPartitionIdValue")));
|
||||
} else if (thePartitionId.hasDefaultPartitionId()) {
|
||||
predicates.add(theCriteriaBuilder.or(
|
||||
theCriteriaBuilder.isNull(theFrom.get("myPartitionIdValue")),
|
||||
theFrom.get("myPartitionIdValue").in(thePartitionId.getPartitionIdsWithoutDefault())));
|
||||
} else {
|
||||
predicates.add(theFrom.get("myPartitionIdValue").in(thePartitionId.getPartitionIds()));
|
||||
}
|
||||
}
|
||||
|
||||
if (myResourceType != null) {
|
||||
validateNotSearchingAllPartitions(thePartitionId);
|
||||
predicates.add(theCriteriaBuilder.equal(theFrom.get("myResourceType"), myResourceType));
|
||||
} else {
|
||||
validateNotSearchingAllPartitions(thePartitionId);
|
||||
}
|
||||
}
|
||||
|
||||
if (myRangeStartInclusive != null) {
|
||||
|
@ -266,7 +275,7 @@ public class HistoryBuilder {
|
|||
.where(
|
||||
theCriteriaBuilder.lessThanOrEqualTo(
|
||||
subQueryResourceHistory.get("myUpdated"), myRangeStartInclusive),
|
||||
theCriteriaBuilder.equal(subQueryResourceHistory.get("myResourceId"), myResourceId));
|
||||
theCriteriaBuilder.equal(subQueryResourceHistory.get("myResourcePid"), myResourceId.toFk()));
|
||||
|
||||
Predicate updatedDatePredicate =
|
||||
theCriteriaBuilder.greaterThanOrEqualTo(theFrom.get("myUpdated"), pastDateSubQuery);
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
package ca.uhn.fhir.jpa.dao;
|
||||
|
||||
import ca.uhn.fhir.jpa.config.JpaConfig;
|
||||
import ca.uhn.fhir.jpa.model.dao.JpaPid;
|
||||
import jakarta.annotation.Nullable;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
@ -33,7 +34,7 @@ public class HistoryBuilderFactory {
|
|||
|
||||
public HistoryBuilder newHistoryBuilder(
|
||||
@Nullable String theResourceType,
|
||||
@Nullable Long theResourceId,
|
||||
@Nullable JpaPid theResourceId,
|
||||
@Nullable Date theRangeStartInclusive,
|
||||
@Nullable Date theRangeEndInclusive) {
|
||||
return (HistoryBuilder) myApplicationContext.getBean(
|
||||
|
|
|
@ -35,7 +35,7 @@ public interface IJpaStorageResourceParser extends IStorageResourceParser<JpaPid
|
|||
*/
|
||||
<R extends IBaseResource> R toResource(
|
||||
Class<R> theResourceType,
|
||||
IBaseResourceEntity theEntity,
|
||||
IBaseResourceEntity<?> theEntity,
|
||||
Collection<BaseTag> theTagList,
|
||||
boolean theForHistoryOperation);
|
||||
|
||||
|
@ -44,7 +44,7 @@ public interface IJpaStorageResourceParser extends IStorageResourceParser<JpaPid
|
|||
* objects pulled from the database
|
||||
*/
|
||||
<R extends IBaseResource> R populateResourceMetadata(
|
||||
IBaseResourceEntity theEntitySource,
|
||||
IBaseResourceEntity<?> theEntitySource,
|
||||
boolean theForHistoryOperation,
|
||||
@Nullable Collection<? extends BaseTag> tagList,
|
||||
long theVersion,
|
||||
|
@ -57,5 +57,5 @@ public interface IJpaStorageResourceParser extends IStorageResourceParser<JpaPid
|
|||
* @param theEntitySource The source
|
||||
* @param theResourceTarget The target
|
||||
*/
|
||||
void updateResourceMetadata(IBaseResourceEntity theEntitySource, IBaseResource theResourceTarget);
|
||||
void updateResourceMetadata(IBaseResourceEntity<?> theEntitySource, IBaseResource theResourceTarget);
|
||||
}
|
||||
|
|
|
@ -232,6 +232,7 @@ public class JpaResourceDaoCodeSystem<T extends IBaseResource> extends BaseHapiF
|
|||
TransactionDetails theTransactionDetails,
|
||||
boolean theForceUpdate,
|
||||
boolean theCreateNewHistoryEntry) {
|
||||
|
||||
ResourceTable retVal = super.updateEntity(
|
||||
theRequest,
|
||||
theResource,
|
||||
|
@ -251,6 +252,15 @@ public class JpaResourceDaoCodeSystem<T extends IBaseResource> extends BaseHapiF
|
|||
myTerminologyCodeSystemStorageSvc.storeNewCodeSystemVersionIfNeeded(
|
||||
cs, (ResourceTable) theEntity, theRequest);
|
||||
}
|
||||
|
||||
/*
|
||||
* Flushing for each stored resource hurts performance, but in this case
|
||||
* it's justified because we don't expect people to be submitting
|
||||
* CodeSystem resources at super high rates, and we need to have the
|
||||
* various writes finished in case a second entry in the same transaction
|
||||
* tries to create a duplicate codesystem.
|
||||
*/
|
||||
myEntityManager.flush();
|
||||
}
|
||||
|
||||
return retVal;
|
||||
|
|
|
@ -33,6 +33,7 @@ import ca.uhn.fhir.jpa.esr.ExternallyStoredResourceServiceRegistry;
|
|||
import ca.uhn.fhir.jpa.esr.IExternallyStoredResourceService;
|
||||
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
||||
import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource;
|
||||
import ca.uhn.fhir.jpa.model.dao.JpaPid;
|
||||
import ca.uhn.fhir.jpa.model.entity.BaseTag;
|
||||
import ca.uhn.fhir.jpa.model.entity.IBaseResourceEntity;
|
||||
import ca.uhn.fhir.jpa.model.entity.PartitionablePartitionId;
|
||||
|
@ -112,13 +113,13 @@ public class JpaStorageResourceParser implements IJpaStorageResourceParser {
|
|||
public IBaseResource toResource(IBasePersistedResource theEntity, boolean theForHistoryOperation) {
|
||||
RuntimeResourceDefinition type = myFhirContext.getResourceDefinition(theEntity.getResourceType());
|
||||
Class<? extends IBaseResource> resourceType = type.getImplementingClass();
|
||||
return toResource(resourceType, (IBaseResourceEntity) theEntity, null, theForHistoryOperation);
|
||||
return toResource(resourceType, (IBaseResourceEntity<JpaPid>) theEntity, null, theForHistoryOperation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R extends IBaseResource> R toResource(
|
||||
Class<R> theResourceType,
|
||||
IBaseResourceEntity theEntity,
|
||||
IBaseResourceEntity<?> theEntity,
|
||||
Collection<BaseTag> theTagList,
|
||||
boolean theForHistoryOperation) {
|
||||
|
||||
|
@ -164,8 +165,8 @@ public class JpaStorageResourceParser implements IJpaStorageResourceParser {
|
|||
provenanceRequestId = history.getRequestId();
|
||||
if (isBlank(provenanceSourceUri) && isBlank(provenanceRequestId)) {
|
||||
if (myStorageSettings.isAccessMetaSourceInformationFromProvenanceTable()) {
|
||||
Optional<ResourceHistoryProvenanceEntity> provenanceOpt =
|
||||
myResourceHistoryProvenanceDao.findById(history.getId());
|
||||
Optional<ResourceHistoryProvenanceEntity> provenanceOpt = myResourceHistoryProvenanceDao.findById(
|
||||
history.getId().asIdAndPartitionId());
|
||||
if (provenanceOpt.isPresent()) {
|
||||
ResourceHistoryProvenanceEntity provenance = provenanceOpt.get();
|
||||
provenanceRequestId = provenance.getRequestId();
|
||||
|
@ -180,13 +181,15 @@ public class JpaStorageResourceParser implements IJpaStorageResourceParser {
|
|||
history = resource.getCurrentVersionEntity();
|
||||
} else {
|
||||
version = theEntity.getVersion();
|
||||
history = myResourceHistoryTableDao.findForIdAndVersion(theEntity.getResourceId(), version);
|
||||
history = myResourceHistoryTableDao.findForIdAndVersion(
|
||||
theEntity.getResourceId().toFk(), version);
|
||||
((ResourceTable) theEntity).setCurrentVersionEntity(history);
|
||||
|
||||
while (history == null) {
|
||||
if (version > 1L) {
|
||||
version--;
|
||||
history = myResourceHistoryTableDao.findForIdAndVersion(theEntity.getResourceId(), version);
|
||||
history = myResourceHistoryTableDao.findForIdAndVersion(
|
||||
theEntity.getResourceId().toFk(), version);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
@ -215,8 +218,8 @@ public class JpaStorageResourceParser implements IJpaStorageResourceParser {
|
|||
provenanceRequestId = history.getRequestId();
|
||||
if (isBlank(provenanceSourceUri) && isBlank(provenanceRequestId)) {
|
||||
if (myStorageSettings.isAccessMetaSourceInformationFromProvenanceTable()) {
|
||||
Optional<ResourceHistoryProvenanceEntity> provenanceOpt =
|
||||
myResourceHistoryProvenanceDao.findById(history.getId());
|
||||
Optional<ResourceHistoryProvenanceEntity> provenanceOpt = myResourceHistoryProvenanceDao.findById(
|
||||
history.getId().asIdAndPartitionId());
|
||||
if (provenanceOpt.isPresent()) {
|
||||
ResourceHistoryProvenanceEntity provenance = provenanceOpt.get();
|
||||
provenanceRequestId = provenance.getRequestId();
|
||||
|
@ -269,7 +272,7 @@ public class JpaStorageResourceParser implements IJpaStorageResourceParser {
|
|||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <R extends IBaseResource> R parseResource(
|
||||
IBaseResourceEntity theEntity,
|
||||
IBaseResourceEntity<?> theEntity,
|
||||
ResourceEncodingEnum theResourceEncoding,
|
||||
String theDecodedResourceText,
|
||||
Class<R> theResourceType) {
|
||||
|
@ -346,7 +349,7 @@ public class JpaStorageResourceParser implements IJpaStorageResourceParser {
|
|||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <R extends IBaseResource> R populateResourceMetadata(
|
||||
IBaseResourceEntity theEntitySource,
|
||||
IBaseResourceEntity<?> theEntitySource,
|
||||
boolean theForHistoryOperation,
|
||||
@Nullable Collection<? extends BaseTag> tagList,
|
||||
long theVersion,
|
||||
|
@ -365,7 +368,7 @@ public class JpaStorageResourceParser implements IJpaStorageResourceParser {
|
|||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <R extends IResource> R populateResourceMetadataHapi(
|
||||
IBaseResourceEntity theEntity,
|
||||
IBaseResourceEntity<?> theEntity,
|
||||
@Nullable Collection<? extends BaseTag> theTagList,
|
||||
boolean theForHistoryOperation,
|
||||
R res,
|
||||
|
@ -519,7 +522,7 @@ public class JpaStorageResourceParser implements IJpaStorageResourceParser {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void updateResourceMetadata(IBaseResourceEntity theEntitySource, IBaseResource theResourceTarget) {
|
||||
public void updateResourceMetadata(IBaseResourceEntity<?> theEntitySource, IBaseResource theResourceTarget) {
|
||||
IIdType id = theEntitySource.getIdDt();
|
||||
if (myFhirContext.getVersion().getVersion().isRi()) {
|
||||
id = myFhirContext.getVersion().newIdType().setValue(id.getValue());
|
||||
|
|
|
@ -21,6 +21,7 @@ package ca.uhn.fhir.jpa.dao;
|
|||
|
||||
import ca.uhn.fhir.context.BaseRuntimeElementDefinition;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jpa.model.dao.JpaPid;
|
||||
import ca.uhn.fhir.parser.DataFormatException;
|
||||
import ca.uhn.fhir.parser.IParserErrorHandler;
|
||||
import ca.uhn.fhir.parser.JsonParser;
|
||||
|
@ -42,7 +43,7 @@ public class TolerantJsonParser extends JsonParser {
|
|||
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(TolerantJsonParser.class);
|
||||
private final FhirContext myContext;
|
||||
private final Long myResourcePid;
|
||||
private final JpaPid myResourcePid;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
|
@ -50,7 +51,8 @@ public class TolerantJsonParser extends JsonParser {
|
|||
* @param theResourcePid The ID of the resource that will be parsed with this parser. It would be ok to change the
|
||||
* datatype for this param if we ever need to since it's only used for logging.
|
||||
*/
|
||||
public TolerantJsonParser(FhirContext theContext, IParserErrorHandler theParserErrorHandler, Long theResourcePid) {
|
||||
public TolerantJsonParser(
|
||||
FhirContext theContext, IParserErrorHandler theParserErrorHandler, JpaPid theResourcePid) {
|
||||
super(theContext, theParserErrorHandler);
|
||||
myContext = theContext;
|
||||
myResourcePid = theResourcePid;
|
||||
|
@ -121,7 +123,7 @@ public class TolerantJsonParser extends JsonParser {
|
|||
}
|
||||
|
||||
public static TolerantJsonParser createWithLenientErrorHandling(
|
||||
FhirContext theContext, @Nullable Long theResourcePid) {
|
||||
FhirContext theContext, @Nullable JpaPid theResourcePid) {
|
||||
LenientErrorHandler errorHandler = new LenientErrorHandler(false).disableAllErrors();
|
||||
return new TolerantJsonParser(theContext, errorHandler, theResourcePid);
|
||||
}
|
||||
|
|
|
@ -89,8 +89,8 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
|||
public class TransactionProcessor extends BaseTransactionProcessor {
|
||||
|
||||
public static final Pattern SINGLE_PARAMETER_MATCH_URL_PATTERN = Pattern.compile("^[^?]+[?][a-z0-9-]+=[^&,]+$");
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(TransactionProcessor.class);
|
||||
public static final int CONDITIONAL_URL_FETCH_CHUNK_SIZE = 100;
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(TransactionProcessor.class);
|
||||
|
||||
@Autowired
|
||||
private ApplicationContext myApplicationContext;
|
||||
|
@ -229,12 +229,12 @@ public class TransactionProcessor extends BaseTransactionProcessor {
|
|||
systemDao.preFetchResources(JpaPid.fromLongList(idsToPreFetch), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("rawtypes")
|
||||
protected void postTransactionProcess(TransactionDetails theTransactionDetails) {
|
||||
Set<IResourcePersistentId> resourceIds = theTransactionDetails.getUpdatedResourceIds();
|
||||
if (resourceIds != null && !resourceIds.isEmpty()) {
|
||||
List<Long> ids = resourceIds.stream().map(r -> (Long) r.getId()).collect(Collectors.toList());
|
||||
|
||||
List<JpaPid> ids = resourceIds.stream().map(r -> (JpaPid) r).collect(Collectors.toList());
|
||||
myResourceSearchUrlSvc.deleteByResIds(ids);
|
||||
}
|
||||
}
|
||||
|
@ -463,7 +463,7 @@ public class TransactionProcessor extends BaseTransactionProcessor {
|
|||
CriteriaBuilder cb = myEntityManager.getCriteriaBuilder();
|
||||
CriteriaQuery<Tuple> cq = cb.createTupleQuery();
|
||||
Root<ResourceIndexedSearchParamToken> from = cq.from(ResourceIndexedSearchParamToken.class);
|
||||
cq.multiselect(from.get("myResourcePid"), from.get(theIndexColumnName));
|
||||
cq.multiselect(from.get("myPartitionIdValue"), from.get("myResourcePid"), from.get(theIndexColumnName));
|
||||
|
||||
Predicate masterPredicate;
|
||||
if (theHashesForIndexColumn.size() == 1) {
|
||||
|
@ -507,21 +507,20 @@ public class TransactionProcessor extends BaseTransactionProcessor {
|
|||
List<Tuple> results = query.getResultList();
|
||||
|
||||
for (Tuple nextResult : results) {
|
||||
Long nextResourcePid = nextResult.get(0, Long.class);
|
||||
Long nextHash = nextResult.get(1, Long.class);
|
||||
Integer nextPartitionId = nextResult.get(0, Integer.class);
|
||||
Long nextResourcePid = nextResult.get(1, Long.class);
|
||||
Long nextHash = nextResult.get(2, Long.class);
|
||||
|
||||
List<MatchUrlToResolve> matchedSearch = hashToSearchMap.get(nextHash);
|
||||
matchedSearch.forEach(matchUrl -> {
|
||||
ourLog.debug("Matched url {} from database", matchUrl.myRequestUrl);
|
||||
if (matchUrl.myShouldPreFetchResourceBody) {
|
||||
theOutputPidsToLoadFully.add(nextResourcePid);
|
||||
}
|
||||
JpaPid pid = JpaPid.fromId(nextResourcePid, nextPartitionId);
|
||||
myMatchResourceUrlService.matchUrlResolved(
|
||||
theTransactionDetails,
|
||||
matchUrl.myResourceDefinition.getName(),
|
||||
matchUrl.myRequestUrl,
|
||||
JpaPid.fromId(nextResourcePid));
|
||||
theTransactionDetails.addResolvedMatchUrl(
|
||||
myFhirContext, matchUrl.myRequestUrl, JpaPid.fromId(nextResourcePid));
|
||||
theTransactionDetails, matchUrl.myResourceDefinition.getName(), matchUrl.myRequestUrl, pid);
|
||||
theTransactionDetails.addResolvedMatchUrl(myFhirContext, matchUrl.myRequestUrl, pid);
|
||||
matchUrl.setResolved(true);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -38,17 +38,17 @@ import java.util.Optional;
|
|||
public interface IMdmLinkJpaRepository
|
||||
extends RevisionRepository<MdmLink, Long, Long>, JpaRepository<MdmLink, Long>, IHapiFhirJpaRepository {
|
||||
@Modifying
|
||||
@Query("DELETE FROM MdmLink f WHERE myGoldenResourcePid = :pid OR mySourcePid = :pid")
|
||||
@Query("DELETE FROM MdmLink f WHERE f.myGoldenResourcePid = :pid OR f.mySourcePid = :pid")
|
||||
int deleteWithAnyReferenceToPid(@Param("pid") Long thePid);
|
||||
|
||||
@Modifying
|
||||
@Query(
|
||||
"DELETE FROM MdmLink f WHERE (myGoldenResourcePid = :pid OR mySourcePid = :pid) AND myMatchResult <> :matchResult")
|
||||
"DELETE FROM MdmLink f WHERE (f.myGoldenResourcePid = :pid OR f.mySourcePid = :pid) AND f.myMatchResult <> :matchResult")
|
||||
int deleteWithAnyReferenceToPidAndMatchResultNot(
|
||||
@Param("pid") Long thePid, @Param("matchResult") MdmMatchResultEnum theMatchResult);
|
||||
|
||||
@Modifying
|
||||
@Query("DELETE FROM MdmLink f WHERE myGoldenResourcePid IN (:goldenPids) OR mySourcePid IN (:goldenPids)")
|
||||
@Query("DELETE FROM MdmLink f WHERE f.myGoldenResourcePid IN (:goldenPids) OR f.mySourcePid IN (:goldenPids)")
|
||||
void deleteLinksWithAnyReferenceToPids(@Param("goldenPids") List<Long> theResourcePids);
|
||||
|
||||
@Modifying
|
||||
|
@ -64,7 +64,7 @@ public interface IMdmLinkJpaRepository
|
|||
"SELECT lookup_links.myGoldenResourcePid as goldenPid, gld_rt.myPartitionIdValue as goldenPartitionId, lookup_links.mySourcePid as sourcePid, lookup_links.myPartitionIdValue as sourcePartitionId "
|
||||
+ "FROM MdmLink lookup_links "
|
||||
+ "INNER JOIN ResourceTable gld_rt "
|
||||
+ "on lookup_links.myGoldenResourcePid=gld_rt.myId "
|
||||
+ "on lookup_links.myGoldenResource=gld_rt "
|
||||
+ "WHERE lookup_links.myMatchResult=:matchResult "
|
||||
+ "AND lookup_links.myGoldenResourcePid IN ("
|
||||
+ "SELECT inner_mdm_link.myGoldenResourcePid FROM MdmLink inner_mdm_link "
|
||||
|
@ -97,7 +97,7 @@ public interface IMdmLinkJpaRepository
|
|||
+ "INNER JOIN MdmLink gld_link "
|
||||
+ "on lookup_link.myGoldenResourcePid=gld_link.myGoldenResourcePid "
|
||||
+ "INNER JOIN ResourceTable gld_rt "
|
||||
+ "on gld_link.myGoldenResourcePid=gld_rt.myId "
|
||||
+ "on gld_link.myGoldenResource=gld_rt "
|
||||
+ "WHERE gld_link.mySourcePid=:sourcePid "
|
||||
+ "AND gld_link.myMatchResult=:matchResult "
|
||||
+ "AND lookup_link.myMatchResult=:matchResult")
|
||||
|
@ -117,7 +117,7 @@ public interface IMdmLinkJpaRepository
|
|||
"SELECT lookup_link.myGoldenResourcePid as goldenPid, gld_rt.myPartitionIdValue as goldenPartitionId, lookup_link.mySourcePid as sourcePid, lookup_link.myPartitionIdValue as sourcePartitionId "
|
||||
+ "FROM MdmLink lookup_link "
|
||||
+ "INNER JOIN ResourceTable gld_rt "
|
||||
+ "on lookup_link.myGoldenResourcePid=gld_rt.myId "
|
||||
+ "on lookup_link.myGoldenResource=gld_rt "
|
||||
+ "WHERE lookup_link.myGoldenResourcePid = :goldenPid "
|
||||
+ "AND lookup_link.myMatchResult = :matchResult")
|
||||
List<MdmPidTuple> expandPidsByGoldenResourcePidAndMatchResult(
|
||||
|
@ -127,7 +127,7 @@ public interface IMdmLinkJpaRepository
|
|||
"SELECT lookup_link.myGoldenResourcePid as goldenPid, gld_rt.myPartitionIdValue as goldenPartitionId, lookup_link.mySourcePid as sourcePid, lookup_link.myPartitionIdValue as sourcePartitionId "
|
||||
+ "FROM MdmLink lookup_link "
|
||||
+ "INNER JOIN ResourceTable gld_rt "
|
||||
+ "on lookup_link.myGoldenResourcePid=gld_rt.myId "
|
||||
+ "on lookup_link.myGoldenResource=gld_rt "
|
||||
+ "WHERE "
|
||||
+ " (lookup_link.myGoldenResourcePid IN (:pids) "
|
||||
+ " OR"
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
*/
|
||||
package ca.uhn.fhir.jpa.dao.data;
|
||||
|
||||
import ca.uhn.fhir.jpa.model.entity.IdAndPartitionId;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceHistoryProvenanceEntity;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
|
@ -26,7 +27,7 @@ import org.springframework.data.jpa.repository.Query;
|
|||
import org.springframework.data.repository.query.Param;
|
||||
|
||||
public interface IResourceHistoryProvenanceDao
|
||||
extends JpaRepository<ResourceHistoryProvenanceEntity, Long>, IHapiFhirJpaRepository {
|
||||
extends JpaRepository<ResourceHistoryProvenanceEntity, IdAndPartitionId>, IHapiFhirJpaRepository {
|
||||
|
||||
@Modifying
|
||||
@Query("DELETE FROM ResourceHistoryProvenanceEntity t WHERE t.myId = :pid")
|
||||
|
|
|
@ -19,7 +19,10 @@
|
|||
*/
|
||||
package ca.uhn.fhir.jpa.dao.data;
|
||||
|
||||
import ca.uhn.fhir.jpa.model.dao.JpaPid;
|
||||
import ca.uhn.fhir.jpa.model.dao.JpaPidFk;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceHistoryTable;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceHistoryTablePk;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Slice;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
@ -29,54 +32,59 @@ import org.springframework.data.repository.query.Param;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
public interface IResourceHistoryTableDao extends JpaRepository<ResourceHistoryTable, Long>, IHapiFhirJpaRepository {
|
||||
public interface IResourceHistoryTableDao
|
||||
extends JpaRepository<ResourceHistoryTable, ResourceHistoryTablePk>, IHapiFhirJpaRepository {
|
||||
|
||||
/**
|
||||
* This is really only intended for unit tests - There can be many versions of resources in
|
||||
* the real world, use a pageable query for real uses.
|
||||
*/
|
||||
@Query("SELECT t FROM ResourceHistoryTable t WHERE t.myResourceId = :resId ORDER BY t.myResourceVersion ASC")
|
||||
List<ResourceHistoryTable> findAllVersionsForResourceIdInOrder(@Param("resId") Long theId);
|
||||
@Query("SELECT t FROM ResourceHistoryTable t WHERE t.myResourcePid = :resId ORDER BY t.myResourceVersion ASC")
|
||||
List<ResourceHistoryTable> findAllVersionsForResourceIdInOrder(@Param("resId") JpaPidFk theId);
|
||||
|
||||
@Query("SELECT t FROM ResourceHistoryTable t WHERE t.myResourceId = :id AND t.myResourceVersion = :version")
|
||||
ResourceHistoryTable findForIdAndVersion(@Param("id") long theId, @Param("version") long theVersion);
|
||||
@Query("SELECT t FROM ResourceHistoryTable t WHERE t.myResourcePid = :id AND t.myResourceVersion = :version")
|
||||
ResourceHistoryTable findForIdAndVersion(@Param("id") JpaPidFk theId, @Param("version") long theVersion);
|
||||
|
||||
@Query(
|
||||
"SELECT t.myId FROM ResourceHistoryTable t WHERE t.myResourceId = :resId AND t.myResourceVersion <> :dontWantVersion")
|
||||
Slice<Long> findForResourceId(
|
||||
Pageable thePage, @Param("resId") Long theId, @Param("dontWantVersion") Long theDontWantVersion);
|
||||
"SELECT t.myId FROM ResourceHistoryTable t WHERE t.myResourcePid = :resId AND t.myResourceVersion <> :dontWantVersion")
|
||||
Slice<ResourceHistoryTablePk> findForResourceId(
|
||||
Pageable thePage, @Param("resId") JpaPidFk theId, @Param("dontWantVersion") Long theDontWantVersion);
|
||||
|
||||
@Query(
|
||||
"SELECT t FROM ResourceHistoryTable t WHERE t.myResourceId = :resId AND t.myResourceVersion <> :dontWantVersion")
|
||||
"SELECT t FROM ResourceHistoryTable t WHERE t.myResourcePid = :resId AND t.myResourceVersion <> :dontWantVersion")
|
||||
Slice<ResourceHistoryTable> findAllVersionsExceptSpecificForResourcePid(
|
||||
Pageable thePage, @Param("resId") Long theId, @Param("dontWantVersion") Long theDontWantVersion);
|
||||
Pageable thePage, @Param("resId") JpaPidFk theId, @Param("dontWantVersion") Long theDontWantVersion);
|
||||
|
||||
@Query("" + "SELECT v.myId FROM ResourceHistoryTable v "
|
||||
+ "LEFT OUTER JOIN ResourceTable t ON (v.myResourceId = t.myId) "
|
||||
@Query("SELECT v.myId FROM ResourceHistoryTable v "
|
||||
+ "LEFT OUTER JOIN ResourceTable t ON (v.myResourceTable = t) "
|
||||
+ "WHERE v.myResourceVersion <> t.myVersion AND "
|
||||
+ "t.myId = :resId")
|
||||
Slice<Long> findIdsOfPreviousVersionsOfResourceId(Pageable thePage, @Param("resId") Long theResourceId);
|
||||
+ "t.myPid = :resId")
|
||||
Slice<ResourceHistoryTablePk> findIdsOfPreviousVersionsOfResourceId(
|
||||
Pageable thePage, @Param("resId") JpaPid theResourceId);
|
||||
|
||||
@Query("" + "SELECT v.myId FROM ResourceHistoryTable v "
|
||||
+ "LEFT OUTER JOIN ResourceTable t ON (v.myResourceId = t.myId) "
|
||||
@Query("SELECT v.myId FROM ResourceHistoryTable v "
|
||||
+ "LEFT OUTER JOIN ResourceTable t ON (v.myResourceTable = t) "
|
||||
+ "WHERE v.myResourceVersion <> t.myVersion AND "
|
||||
+ "t.myResourceType = :restype")
|
||||
Slice<Long> findIdsOfPreviousVersionsOfResources(Pageable thePage, @Param("restype") String theResourceName);
|
||||
Slice<ResourceHistoryTablePk> findIdsOfPreviousVersionsOfResources(
|
||||
Pageable thePage, @Param("restype") String theResourceName);
|
||||
|
||||
@Query("" + "SELECT v.myId FROM ResourceHistoryTable v "
|
||||
+ "LEFT OUTER JOIN ResourceTable t ON (v.myResourceId = t.myId) "
|
||||
+ "LEFT OUTER JOIN ResourceTable t ON (v.myResourceTable = t) "
|
||||
+ "WHERE v.myResourceVersion <> t.myVersion")
|
||||
Slice<Long> findIdsOfPreviousVersionsOfResources(Pageable thePage);
|
||||
Slice<ResourceHistoryTablePk> findIdsOfPreviousVersionsOfResources(Pageable thePage);
|
||||
|
||||
@Modifying
|
||||
@Query(
|
||||
"UPDATE ResourceHistoryTable r SET r.myResourceVersion = :newVersion WHERE r.myResourceId = :id AND r.myResourceVersion = :oldVersion")
|
||||
"UPDATE ResourceHistoryTable r SET r.myResourceVersion = :newVersion WHERE r.myResourcePid = :id AND r.myResourceVersion = :oldVersion")
|
||||
void updateVersion(
|
||||
@Param("id") long theId, @Param("oldVersion") long theOldVersion, @Param("newVersion") long theNewVersion);
|
||||
@Param("id") JpaPidFk theId,
|
||||
@Param("oldVersion") long theOldVersion,
|
||||
@Param("newVersion") long theNewVersion);
|
||||
|
||||
@Modifying
|
||||
@Query("DELETE FROM ResourceHistoryTable t WHERE t.myId = :pid")
|
||||
void deleteByPid(@Param("pid") Long theId);
|
||||
void deleteByPid(@Param("pid") ResourceHistoryTablePk theId);
|
||||
|
||||
/**
|
||||
* This method is only for use in unit tests - It is used to move the stored resource body contents from the new
|
||||
|
@ -88,11 +96,11 @@ public interface IResourceHistoryTableDao extends JpaRepository<ResourceHistoryT
|
|||
@Modifying
|
||||
@Query(
|
||||
"UPDATE ResourceHistoryTable r SET r.myResourceTextVc = null, r.myResource = :text, r.myEncoding = 'JSONC' WHERE r.myId = :pid")
|
||||
void updateNonInlinedContents(@Param("text") byte[] theText, @Param("pid") long thePid);
|
||||
void updateNonInlinedContents(@Param("text") byte[] theText, @Param("pid") ResourceHistoryTablePk thePid);
|
||||
|
||||
@Query("SELECT v FROM ResourceHistoryTable v " + "JOIN FETCH v.myResourceTable t "
|
||||
+ "WHERE v.myResourceId IN (:pids) "
|
||||
+ "WHERE v.myResourcePid IN (:pids) "
|
||||
+ "AND t.myVersion = v.myResourceVersion")
|
||||
List<ResourceHistoryTable> findCurrentVersionsByResourcePidsAndFetchResourceTable(
|
||||
@Param("pids") List<Long> theVersionlessPids);
|
||||
@Param("pids") List<JpaPidFk> theVersionlessPids);
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
*/
|
||||
package ca.uhn.fhir.jpa.dao.data;
|
||||
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceHistoryTablePk;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceHistoryTag;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
|
@ -30,10 +31,10 @@ import java.util.Collection;
|
|||
public interface IResourceHistoryTagDao extends JpaRepository<ResourceHistoryTag, Long>, IHapiFhirJpaRepository {
|
||||
|
||||
@Modifying
|
||||
@Query("DELETE FROM ResourceHistoryTag t WHERE t.myResourceHistoryPid = :historyPid")
|
||||
void deleteByPid(@Param("historyPid") Long theResourceHistoryTablePid);
|
||||
@Query("DELETE FROM ResourceHistoryTag t WHERE t.myResourceHistory.myId = :historyPid")
|
||||
void deleteByPid(@Param("historyPid") ResourceHistoryTablePk theResourceHistoryTablePid);
|
||||
|
||||
@Query(
|
||||
"SELECT t FROM ResourceHistoryTag t INNER JOIN FETCH t.myTag WHERE t.myResourceHistory.myId IN (:historyPids)")
|
||||
Collection<ResourceHistoryTag> findByVersionIds(@Param("historyPids") Collection<Long> theIdList);
|
||||
Collection<ResourceHistoryTag> findByVersionIds(@Param("historyPids") Collection<ResourceHistoryTablePk> theIdList);
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
*/
|
||||
package ca.uhn.fhir.jpa.dao.data;
|
||||
|
||||
import ca.uhn.fhir.jpa.model.dao.JpaPid;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedComboStringUnique;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
|
@ -32,10 +33,10 @@ public interface IResourceIndexedComboStringUniqueDao extends JpaRepository<Reso
|
|||
@Query("SELECT r FROM ResourceIndexedComboStringUnique r WHERE r.myIndexString = :str")
|
||||
ResourceIndexedComboStringUnique findByQueryString(@Param("str") String theQueryString);
|
||||
|
||||
@Query("SELECT r FROM ResourceIndexedComboStringUnique r WHERE r.myResourceId = :resId")
|
||||
List<ResourceIndexedComboStringUnique> findAllForResourceIdForUnitTest(@Param("resId") Long theResourceId);
|
||||
@Query("SELECT r FROM ResourceIndexedComboStringUnique r WHERE r.myResource.myPid = :resId")
|
||||
List<ResourceIndexedComboStringUnique> findAllForResourceIdForUnitTest(@Param("resId") JpaPid theResourceId);
|
||||
|
||||
@Modifying
|
||||
@Query("delete from ResourceIndexedComboStringUnique t WHERE t.myResourceId = :resid")
|
||||
void deleteByResourceId(@Param("resid") Long theResourcePid);
|
||||
@Query("delete from ResourceIndexedComboStringUnique t WHERE t.myResource.myPid = :resid")
|
||||
void deleteByResourceId(@Param("resid") JpaPid theResourcePid);
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
*/
|
||||
package ca.uhn.fhir.jpa.dao.data;
|
||||
|
||||
import ca.uhn.fhir.jpa.model.dao.JpaPid;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedComboTokenNonUnique;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
|
@ -29,6 +30,6 @@ public interface IResourceIndexedComboTokensNonUniqueDao
|
|||
extends JpaRepository<ResourceIndexedComboTokenNonUnique, Long> {
|
||||
|
||||
@Modifying
|
||||
@Query("DELETE FROM ResourceIndexedComboTokenNonUnique t WHERE t.myResourceId = :res_id")
|
||||
void deleteByResourceId(@Param("res_id") Long theResourcePid);
|
||||
@Query("DELETE FROM ResourceIndexedComboTokenNonUnique t WHERE t.myResource.myPid = :res_id")
|
||||
void deleteByResourceId(@Param("res_id") JpaPid theResourcePid);
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
*/
|
||||
package ca.uhn.fhir.jpa.dao.data;
|
||||
|
||||
import ca.uhn.fhir.jpa.model.dao.JpaPid;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamCoords;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
|
@ -28,6 +29,6 @@ import org.springframework.data.repository.query.Param;
|
|||
public interface IResourceIndexedSearchParamCoordsDao
|
||||
extends JpaRepository<ResourceIndexedSearchParamCoords, Long>, IHapiFhirJpaRepository {
|
||||
@Modifying
|
||||
@Query("delete from ResourceIndexedSearchParamCoords t WHERE t.myResourcePid = :resid")
|
||||
void deleteByResourceId(@Param("resid") Long theResourcePid);
|
||||
@Query("delete from ResourceIndexedSearchParamCoords t WHERE t.myResource.myPid = :resid")
|
||||
void deleteByResourceId(@Param("resid") JpaPid theResourcePid);
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
*/
|
||||
package ca.uhn.fhir.jpa.dao.data;
|
||||
|
||||
import ca.uhn.fhir.jpa.model.dao.JpaPid;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamDate;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
|
@ -30,9 +31,9 @@ import java.util.List;
|
|||
public interface IResourceIndexedSearchParamDateDao
|
||||
extends JpaRepository<ResourceIndexedSearchParamDate, Long>, IHapiFhirJpaRepository {
|
||||
@Modifying
|
||||
@Query("delete from ResourceIndexedSearchParamDate t WHERE t.myResourcePid = :resid")
|
||||
void deleteByResourceId(@Param("resid") Long theResourcePid);
|
||||
@Query("delete from ResourceIndexedSearchParamDate t WHERE t.myResource.myPid = :resid")
|
||||
void deleteByResourceId(@Param("resid") JpaPid theResourcePid);
|
||||
|
||||
@Query("SELECT t FROM ResourceIndexedSearchParamDate t WHERE t.myResourcePid = :resId")
|
||||
List<ResourceIndexedSearchParamDate> findAllForResourceId(@Param("resId") Long thePatientId);
|
||||
@Query("SELECT t FROM ResourceIndexedSearchParamDate t WHERE t.myResource.myPid = :resId")
|
||||
List<ResourceIndexedSearchParamDate> findAllForResourceId(@Param("resId") JpaPid thePatientId);
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
*/
|
||||
package ca.uhn.fhir.jpa.dao.data;
|
||||
|
||||
import ca.uhn.fhir.jpa.model.dao.JpaPid;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamNumber;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
|
@ -28,6 +29,6 @@ import org.springframework.data.repository.query.Param;
|
|||
public interface IResourceIndexedSearchParamNumberDao
|
||||
extends JpaRepository<ResourceIndexedSearchParamNumber, Long>, IHapiFhirJpaRepository {
|
||||
@Modifying
|
||||
@Query("delete from ResourceIndexedSearchParamNumber t WHERE t.myResourcePid = :resid")
|
||||
void deleteByResourceId(@Param("resid") Long theResourcePid);
|
||||
@Query("delete from ResourceIndexedSearchParamNumber t WHERE t.myResource.myPid = :resid")
|
||||
void deleteByResourceId(@Param("resid") JpaPid theResourcePid);
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
*/
|
||||
package ca.uhn.fhir.jpa.dao.data;
|
||||
|
||||
import ca.uhn.fhir.jpa.model.dao.JpaPid;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamQuantity;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
|
@ -28,6 +29,6 @@ import org.springframework.data.repository.query.Param;
|
|||
public interface IResourceIndexedSearchParamQuantityDao
|
||||
extends JpaRepository<ResourceIndexedSearchParamQuantity, Long>, IHapiFhirJpaRepository {
|
||||
@Modifying
|
||||
@Query("delete from ResourceIndexedSearchParamQuantity t WHERE t.myResourcePid = :resid")
|
||||
void deleteByResourceId(@Param("resid") Long theResourcePid);
|
||||
@Query("delete from ResourceIndexedSearchParamQuantity t WHERE t.myResource.myPid = :resid")
|
||||
void deleteByResourceId(@Param("resid") JpaPid theResourcePid);
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
*/
|
||||
package ca.uhn.fhir.jpa.dao.data;
|
||||
|
||||
import ca.uhn.fhir.jpa.model.dao.JpaPid;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamQuantityNormalized;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
|
@ -28,6 +29,6 @@ import org.springframework.data.repository.query.Param;
|
|||
public interface IResourceIndexedSearchParamQuantityNormalizedDao
|
||||
extends JpaRepository<ResourceIndexedSearchParamQuantityNormalized, Long>, IHapiFhirJpaRepository {
|
||||
@Modifying
|
||||
@Query("delete from ResourceIndexedSearchParamQuantityNormalized t WHERE t.myResourcePid = :resid")
|
||||
void deleteByResourceId(@Param("resid") Long theResourcePid);
|
||||
@Query("delete from ResourceIndexedSearchParamQuantityNormalized t WHERE t.myResource.myPid = :resid")
|
||||
void deleteByResourceId(@Param("resid") JpaPid theResourcePid);
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
*/
|
||||
package ca.uhn.fhir.jpa.dao.data;
|
||||
|
||||
import ca.uhn.fhir.jpa.model.dao.JpaPid;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamString;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
|
@ -31,9 +32,9 @@ public interface IResourceIndexedSearchParamStringDao
|
|||
extends JpaRepository<ResourceIndexedSearchParamString, Long>, IHapiFhirJpaRepository {
|
||||
|
||||
@Modifying
|
||||
@Query("DELETE FROM ResourceIndexedSearchParamString t WHERE t.myResourcePid = :resId")
|
||||
void deleteByResourceId(@Param("resId") Long theResourcePid);
|
||||
@Query("DELETE FROM ResourceIndexedSearchParamString t WHERE t.myResource.myPid = :resId")
|
||||
void deleteByResourceId(@Param("resId") JpaPid theResourcePid);
|
||||
|
||||
@Query("SELECT t FROM ResourceIndexedSearchParamString t WHERE t.myResourcePid = :resId")
|
||||
List<ResourceIndexedSearchParamString> findAllForResourceId(@Param("resId") Long thePatientId);
|
||||
@Query("SELECT t FROM ResourceIndexedSearchParamString t WHERE t.myResource.myPid = :resId")
|
||||
List<ResourceIndexedSearchParamString> findAllForResourceId(@Param("resId") JpaPid thePatientId);
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
*/
|
||||
package ca.uhn.fhir.jpa.dao.data;
|
||||
|
||||
import ca.uhn.fhir.jpa.model.dao.JpaPid;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamToken;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
|
@ -28,10 +29,10 @@ import org.springframework.data.repository.query.Param;
|
|||
public interface IResourceIndexedSearchParamTokenDao
|
||||
extends JpaRepository<ResourceIndexedSearchParamToken, Long>, IHapiFhirJpaRepository {
|
||||
|
||||
@Query("select count(*) from ResourceIndexedSearchParamToken t WHERE t.myResourcePid = :resid")
|
||||
int countForResourceId(@Param("resid") Long theResourcePid);
|
||||
@Query("select count(*) from ResourceIndexedSearchParamToken t WHERE t.myResource.myPid = :resid")
|
||||
int countForResourceId(@Param("resid") JpaPid theResourcePid);
|
||||
|
||||
@Modifying
|
||||
@Query("delete from ResourceIndexedSearchParamToken t WHERE t.myResourcePid = :resid")
|
||||
void deleteByResourceId(@Param("resid") Long theResourcePid);
|
||||
@Query("delete from ResourceIndexedSearchParamToken t WHERE t.myResource.myPid = :resid")
|
||||
void deleteByResourceId(@Param("resid") JpaPid theResourcePid);
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
*/
|
||||
package ca.uhn.fhir.jpa.dao.data;
|
||||
|
||||
import ca.uhn.fhir.jpa.model.dao.JpaPid;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamUri;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
|
@ -31,9 +32,9 @@ public interface IResourceIndexedSearchParamUriDao
|
|||
extends JpaRepository<ResourceIndexedSearchParamUri, Long>, IHapiFhirJpaRepository {
|
||||
|
||||
@Query("SELECT DISTINCT p.myUri FROM ResourceIndexedSearchParamUri p WHERE p.myHashIdentity = :hash_identity")
|
||||
public Collection<String> findAllByHashIdentity(@Param("hash_identity") long theHashIdentity);
|
||||
Collection<String> findAllByHashIdentity(@Param("hash_identity") long theHashIdentity);
|
||||
|
||||
@Modifying
|
||||
@Query("delete from ResourceIndexedSearchParamUri t WHERE t.myResourcePid = :resid")
|
||||
void deleteByResourceId(@Param("resid") Long theResourcePid);
|
||||
@Query("delete from ResourceIndexedSearchParamUri t WHERE t.myResource.myPid = :resid")
|
||||
void deleteByResourceId(@Param("resid") JpaPid theResourcePid);
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
*/
|
||||
package ca.uhn.fhir.jpa.dao.data;
|
||||
|
||||
import ca.uhn.fhir.jpa.model.dao.JpaPid;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceLink;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
|
@ -30,14 +31,14 @@ import java.util.List;
|
|||
public interface IResourceLinkDao extends JpaRepository<ResourceLink, Long>, IHapiFhirJpaRepository {
|
||||
|
||||
@Modifying
|
||||
@Query("DELETE FROM ResourceLink t WHERE t.mySourceResourcePid = :resId")
|
||||
void deleteByResourceId(@Param("resId") Long theResourcePid);
|
||||
@Query("DELETE FROM ResourceLink t WHERE t.mySourceResource.myPid = :resId")
|
||||
void deleteByResourceId(@Param("resId") JpaPid theResourcePid);
|
||||
|
||||
@Query("SELECT t FROM ResourceLink t WHERE t.mySourceResourcePid = :resId")
|
||||
List<ResourceLink> findAllForSourceResourceId(@Param("resId") Long thePatientId);
|
||||
@Query("SELECT t FROM ResourceLink t WHERE t.mySourceResource.myPid = :resId")
|
||||
List<ResourceLink> findAllForSourceResourceId(@Param("resId") JpaPid thePatientId);
|
||||
|
||||
@Query("SELECT t FROM ResourceLink t WHERE t.myTargetResourcePid in :resIds")
|
||||
List<ResourceLink> findWithTargetPidIn(@Param("resIds") List<Long> thePids);
|
||||
@Query("SELECT t FROM ResourceLink t WHERE t.myTargetResource.myPid in :resIds")
|
||||
List<ResourceLink> findWithTargetPidIn(@Param("resIds") List<JpaPid> thePids);
|
||||
|
||||
/**
|
||||
* Loads a collection of ResourceLink entities by PID, but also eagerly fetches
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
package ca.uhn.fhir.jpa.dao.data;
|
||||
|
||||
import ca.uhn.fhir.jpa.dao.data.custom.IForcedIdQueries;
|
||||
import ca.uhn.fhir.jpa.model.dao.JpaPid;
|
||||
import ca.uhn.fhir.jpa.model.entity.EntityIndexStatusEnum;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
|
@ -40,17 +41,17 @@ import java.util.stream.Stream;
|
|||
|
||||
@Transactional(propagation = Propagation.MANDATORY)
|
||||
public interface IResourceTableDao
|
||||
extends JpaRepository<ResourceTable, Long>, IHapiFhirJpaRepository, IForcedIdQueries {
|
||||
extends JpaRepository<ResourceTable, JpaPid>, IHapiFhirJpaRepository, IForcedIdQueries {
|
||||
|
||||
@Query("SELECT t.myId FROM ResourceTable t WHERE t.myDeleted IS NOT NULL")
|
||||
Slice<Long> findIdsOfDeletedResources(Pageable thePageable);
|
||||
@Query("SELECT t.myPid FROM ResourceTable t WHERE t.myDeleted IS NOT NULL")
|
||||
Slice<JpaPid> findIdsOfDeletedResources(Pageable thePageable);
|
||||
|
||||
@Query("SELECT t.myId FROM ResourceTable t WHERE t.myResourceType = :restype AND t.myDeleted IS NOT NULL")
|
||||
Slice<Long> findIdsOfDeletedResourcesOfType(Pageable thePageable, @Param("restype") String theResourceName);
|
||||
@Query("SELECT t.myPid FROM ResourceTable t WHERE t.myResourceType = :restype AND t.myDeleted IS NOT NULL")
|
||||
Slice<JpaPid> findIdsOfDeletedResourcesOfType(Pageable thePageable, @Param("restype") String theResourceName);
|
||||
|
||||
@Query(
|
||||
"SELECT t.myId FROM ResourceTable t WHERE t.myId = :resid AND t.myResourceType = :restype AND t.myDeleted IS NOT NULL")
|
||||
Slice<Long> findIdsOfDeletedResourcesOfType(
|
||||
"SELECT t.myPid FROM ResourceTable t WHERE t.myPid.myId = :resid AND t.myResourceType = :restype AND t.myDeleted IS NOT NULL")
|
||||
Slice<JpaPid> findIdsOfDeletedResourcesOfType(
|
||||
Pageable thePageable, @Param("resid") Long theResourceId, @Param("restype") String theResourceName);
|
||||
|
||||
@Query(
|
||||
|
@ -58,94 +59,70 @@ public interface IResourceTableDao
|
|||
List<Map<?, ?>> getResourceCounts();
|
||||
|
||||
@Query(
|
||||
"SELECT t.myId FROM ResourceTable t WHERE t.myUpdated >= :low AND t.myUpdated <= :high ORDER BY t.myUpdated DESC")
|
||||
Slice<Long> findIdsOfResourcesWithinUpdatedRangeOrderedFromNewest(
|
||||
"SELECT t.myPid FROM ResourceTable t WHERE t.myUpdated >= :low AND t.myUpdated <= :high ORDER BY t.myUpdated DESC")
|
||||
Slice<JpaPid> findIdsOfResourcesWithinUpdatedRangeOrderedFromNewest(
|
||||
Pageable thePage, @Param("low") Date theLow, @Param("high") Date theHigh);
|
||||
|
||||
@Query(
|
||||
"SELECT t.myId FROM ResourceTable t WHERE t.myUpdated >= :low AND t.myUpdated <= :high ORDER BY t.myUpdated ASC")
|
||||
Slice<Long> findIdsOfResourcesWithinUpdatedRangeOrderedFromOldest(
|
||||
"SELECT t.myPid FROM ResourceTable t WHERE t.myUpdated >= :low AND t.myUpdated <= :high ORDER BY t.myUpdated ASC")
|
||||
Slice<JpaPid> findIdsOfResourcesWithinUpdatedRangeOrderedFromOldest(
|
||||
Pageable thePage, @Param("low") Date theLow, @Param("high") Date theHigh);
|
||||
|
||||
@Query(
|
||||
"SELECT t.myId, t.myResourceType, t.myUpdated FROM ResourceTable t WHERE t.myUpdated >= :low AND t.myUpdated <= :high ORDER BY t.myUpdated ASC")
|
||||
"SELECT t.myPid, t.myResourceType, t.myUpdated FROM ResourceTable t WHERE t.myUpdated >= :low AND t.myUpdated <= :high ORDER BY t.myUpdated ASC")
|
||||
Stream<Object[]> streamIdsTypesAndUpdateTimesOfResourcesWithinUpdatedRangeOrderedFromOldest(
|
||||
@Param("low") Date theLow, @Param("high") Date theHigh);
|
||||
|
||||
/**
|
||||
* @return List of arrays containing [PID, resourceType, lastUpdated]
|
||||
*/
|
||||
@Query(
|
||||
"SELECT t.myId, t.myResourceType, t.myUpdated FROM ResourceTable t WHERE t.myUpdated >= :low AND t.myUpdated <= :high AND t.myPartitionIdValue IN (:partition_ids) ORDER BY t.myUpdated ASC")
|
||||
Slice<Object[]> findIdsTypesAndUpdateTimesOfResourcesWithinUpdatedRangeOrderedFromOldestForPartitionIds(
|
||||
Pageable thePage,
|
||||
@Param("low") Date theLow,
|
||||
@Param("high") Date theHigh,
|
||||
@Param("partition_ids") List<Integer> theRequestPartitionIds);
|
||||
|
||||
@Query(
|
||||
"SELECT t.myId, t.myResourceType, t.myUpdated FROM ResourceTable t WHERE t.myUpdated >= :low AND t.myUpdated <= :high AND t.myPartitionIdValue IN (:partition_ids) ORDER BY t.myUpdated ASC")
|
||||
"SELECT t.myPid, t.myResourceType, t.myUpdated FROM ResourceTable t WHERE t.myUpdated >= :low AND t.myUpdated <= :high AND t.myPartitionIdValue IN (:partition_ids) ORDER BY t.myUpdated ASC")
|
||||
Stream<Object[]> streamIdsTypesAndUpdateTimesOfResourcesWithinUpdatedRangeOrderedFromOldestForPartitionIds(
|
||||
@Param("low") Date theLow,
|
||||
@Param("high") Date theHigh,
|
||||
@Param("partition_ids") List<Integer> theRequestPartitionIds);
|
||||
|
||||
/**
|
||||
* @return List of arrays containing [PID, resourceType, lastUpdated]
|
||||
*/
|
||||
@Query(
|
||||
"SELECT t.myId, t.myResourceType, t.myUpdated FROM ResourceTable t WHERE t.myUpdated >= :low AND t.myUpdated <= :high ORDER BY t.myUpdated ASC")
|
||||
Slice<Object[]> findIdsTypesAndUpdateTimesOfResourcesWithinUpdatedRangeOrderedFromOldestForDefaultPartition(
|
||||
Pageable thePage, @Param("low") Date theLow, @Param("high") Date theHigh);
|
||||
|
||||
@Query(
|
||||
"SELECT t.myId, t.myResourceType, t.myUpdated FROM ResourceTable t WHERE t.myUpdated >= :low AND t.myUpdated <= :high ORDER BY t.myUpdated ASC")
|
||||
"SELECT t.myPid, t.myResourceType, t.myUpdated FROM ResourceTable t WHERE t.myUpdated >= :low AND t.myUpdated <= :high ORDER BY t.myUpdated ASC")
|
||||
Stream<Object[]> streamIdsTypesAndUpdateTimesOfResourcesWithinUpdatedRangeOrderedFromOldestForDefaultPartition(
|
||||
@Param("low") Date theLow, @Param("high") Date theHigh);
|
||||
|
||||
// TODO in the future, consider sorting by pid as well so batch jobs process in the same order across restarts
|
||||
@Query(
|
||||
"SELECT t.myId FROM ResourceTable t WHERE t.myUpdated >= :low AND t.myUpdated <= :high AND t.myPartitionIdValue = :partition_id ORDER BY t.myUpdated ASC")
|
||||
Slice<Long> findIdsOfPartitionedResourcesWithinUpdatedRangeOrderedFromOldest(
|
||||
Pageable thePage,
|
||||
@Param("low") Date theLow,
|
||||
@Param("high") Date theHigh,
|
||||
@Param("partition_id") Integer theRequestPartitionId);
|
||||
|
||||
@Query(
|
||||
"SELECT t.myId FROM ResourceTable t WHERE t.myUpdated >= :low AND t.myUpdated <= :high AND t.myResourceType = :restype ORDER BY t.myUpdated ASC")
|
||||
Slice<Long> findIdsOfResourcesWithinUpdatedRangeOrderedFromOldest(
|
||||
"SELECT t.myPid FROM ResourceTable t WHERE t.myUpdated >= :low AND t.myUpdated <= :high AND t.myResourceType = :restype ORDER BY t.myUpdated ASC")
|
||||
Slice<JpaPid> findIdsOfResourcesWithinUpdatedRangeOrderedFromOldest(
|
||||
Pageable thePage,
|
||||
@Param("restype") String theResourceType,
|
||||
@Param("low") Date theLow,
|
||||
@Param("high") Date theHigh);
|
||||
|
||||
@Modifying
|
||||
@Query("UPDATE ResourceTable t SET t.myIndexStatus = :status WHERE t.myId = :id")
|
||||
void updateIndexStatus(@Param("id") Long theId, @Param("status") EntityIndexStatusEnum theIndexStatus);
|
||||
@Query("UPDATE ResourceTable t SET t.myIndexStatus = :status WHERE t.myPid = :id")
|
||||
void updateIndexStatus(@Param("id") JpaPid theId, @Param("status") EntityIndexStatusEnum theIndexStatus);
|
||||
|
||||
@Modifying
|
||||
@Query("UPDATE ResourceTable t SET t.myUpdated = :updated WHERE t.myId = :id")
|
||||
void updateLastUpdated(@Param("id") Long theId, @Param("updated") Date theUpdated);
|
||||
@Query("UPDATE ResourceTable t SET t.myUpdated = :updated WHERE t.myPid = :id")
|
||||
void updateLastUpdated(@Param("id") JpaPid theId, @Param("updated") Date theUpdated);
|
||||
|
||||
@Modifying
|
||||
@Query("DELETE FROM ResourceTable t WHERE t.myId = :pid")
|
||||
void deleteByPid(@Param("pid") Long theId);
|
||||
@Query("DELETE FROM ResourceTable t WHERE t.myPid = :pid")
|
||||
void deleteByPid(@Param("pid") JpaPid theId);
|
||||
|
||||
/**
|
||||
* This method returns a Collection where each row is an element in the collection. Each element in the collection
|
||||
* is an object array, where the order matters (the array represents columns returned by the query). Be careful if you change this query in any way.
|
||||
*/
|
||||
@Query(
|
||||
"SELECT t.myResourceType, t.myId, t.myDeleted, t.myPartitionIdValue, t.myPartitionDateValue FROM ResourceTable t WHERE t.myId IN (:pid)")
|
||||
"SELECT t.myResourceType, t.myPid.myId, t.myDeleted, t.myPartitionIdValue, t.myPartitionDateValue FROM ResourceTable t WHERE t.myPid.myId IN (:pid)")
|
||||
Collection<Object[]> findLookupFieldsByResourcePid(@Param("pid") List<Long> thePids);
|
||||
|
||||
@Query(
|
||||
"SELECT t.myResourceType, t.myPid.myId, t.myDeleted, t.myPartitionIdValue, t.myPartitionDateValue FROM ResourceTable t WHERE t.myPid IN (:pid)")
|
||||
Collection<Object[]> findLookupFieldsByResourcePidWithPartitionId(@Param("pid") List<JpaPid> thePids);
|
||||
|
||||
/**
|
||||
* This method returns a Collection where each row is an element in the collection. Each element in the collection
|
||||
* is an object array, where the order matters (the array represents columns returned by the query). Be careful if you change this query in any way.
|
||||
*/
|
||||
@Query(
|
||||
"SELECT t.myResourceType, t.myId, t.myDeleted, t.myPartitionIdValue, t.myPartitionDateValue FROM ResourceTable t WHERE t.myId IN (:pid) AND t.myPartitionIdValue IN :partition_id")
|
||||
"SELECT t.myResourceType, t.myPid.myId, t.myDeleted, t.myPartitionIdValue, t.myPartitionDateValue FROM ResourceTable t WHERE t.myPid.myId IN (:pid) AND t.myPartitionIdValue IN :partition_id")
|
||||
Collection<Object[]> findLookupFieldsByResourcePidInPartitionIds(
|
||||
@Param("pid") List<Long> thePids, @Param("partition_id") Collection<Integer> thePartitionId);
|
||||
|
||||
|
@ -154,7 +131,7 @@ public interface IResourceTableDao
|
|||
* is an object array, where the order matters (the array represents columns returned by the query). Be careful if you change this query in any way.
|
||||
*/
|
||||
@Query(
|
||||
"SELECT t.myResourceType, t.myId, t.myDeleted, t.myPartitionIdValue, t.myPartitionDateValue FROM ResourceTable t WHERE t.myId IN (:pid) AND (t.myPartitionIdValue IS NULL OR t.myPartitionIdValue IN :partition_id)")
|
||||
"SELECT t.myResourceType, t.myPid.myId, t.myDeleted, t.myPartitionIdValue, t.myPartitionDateValue FROM ResourceTable t WHERE t.myPid.myId IN (:pid) AND (t.myPartitionIdValue IS NULL OR t.myPartitionIdValue IN :partition_id)")
|
||||
Collection<Object[]> findLookupFieldsByResourcePidInPartitionIdsOrNullPartition(
|
||||
@Param("pid") List<Long> thePids, @Param("partition_id") Collection<Integer> thePartitionId);
|
||||
|
||||
|
@ -163,42 +140,49 @@ public interface IResourceTableDao
|
|||
* is an object array, where the order matters (the array represents columns returned by the query). Be careful if you change this query in any way.
|
||||
*/
|
||||
@Query(
|
||||
"SELECT t.myResourceType, t.myId, t.myDeleted, t.myPartitionIdValue, t.myPartitionDateValue FROM ResourceTable t WHERE t.myId IN (:pid) AND t.myPartitionIdValue IS NULL")
|
||||
"SELECT t.myResourceType, t.myPid.myId, t.myDeleted, t.myPartitionIdValue, t.myPartitionDateValue FROM ResourceTable t WHERE t.myPid.myId IN (:pid) AND t.myPartitionIdValue IS NULL")
|
||||
Collection<Object[]> findLookupFieldsByResourcePidInPartitionNull(@Param("pid") List<Long> thePids);
|
||||
|
||||
@Query("SELECT t.myVersion FROM ResourceTable t WHERE t.myId = :pid")
|
||||
Long findCurrentVersionByPid(@Param("pid") Long thePid);
|
||||
@Query("SELECT t.myVersion FROM ResourceTable t WHERE t.myPid = :pid")
|
||||
Long findCurrentVersionByPid(@Param("pid") JpaPid thePid);
|
||||
|
||||
/**
|
||||
* This query will return rows with the following values:
|
||||
* Id (resource pid - long), ResourceType (Patient, etc), version (long)
|
||||
* Id (JpaPid), FhirId, ResourceType (Patient, etc), version (long)
|
||||
* Order matters!
|
||||
*
|
||||
* @param pid - list of pids to get versions for
|
||||
* @return
|
||||
*/
|
||||
@Query("SELECT t.myId, t.myResourceType, t.myVersion FROM ResourceTable t WHERE t.myId IN ( :pid )")
|
||||
Collection<Object[]> getResourceVersionsForPid(@Param("pid") List<Long> pid);
|
||||
@Query("SELECT t.myPid, t.myResourceType, t.myFhirId, t.myVersion FROM ResourceTable t WHERE t.myPid IN ( :pid )")
|
||||
Collection<Object[]> getResourceVersionsForPid(@Param("pid") Collection<JpaPid> pid);
|
||||
|
||||
@Query("SELECT t FROM ResourceTable t WHERE t.myPartitionId.myPartitionId IS NULL AND t.myId = :pid")
|
||||
@Query("SELECT t FROM ResourceTable t WHERE t.myPartitionIdValue IS NULL AND t.myPid.myId = :pid")
|
||||
Optional<ResourceTable> readByPartitionIdNull(@Param("pid") Long theResourceId);
|
||||
|
||||
@Query("SELECT t FROM ResourceTable t WHERE t.myPartitionId.myPartitionId = :partitionId AND t.myId = :pid")
|
||||
@Query("SELECT t FROM ResourceTable t WHERE t.myPartitionIdValue = :partitionId AND t.myPid.myId = :pid")
|
||||
Optional<ResourceTable> readByPartitionId(
|
||||
@Param("partitionId") int thePartitionId, @Param("pid") Long theResourceId);
|
||||
|
||||
@Query(
|
||||
"SELECT t FROM ResourceTable t WHERE (t.myPartitionId.myPartitionId IS NULL OR t.myPartitionId.myPartitionId IN (:partitionIds)) AND t.myId = :pid")
|
||||
"SELECT t FROM ResourceTable t WHERE (t.myPartitionIdValue IS NULL OR t.myPartitionIdValue IN (:partitionIds)) AND t.myPid.myId = :pid")
|
||||
Optional<ResourceTable> readByPartitionIdsOrNull(
|
||||
@Param("partitionIds") Collection<Integer> thrValues, @Param("pid") Long theResourceId);
|
||||
|
||||
@Query("SELECT t FROM ResourceTable t WHERE t.myPartitionId.myPartitionId IN (:partitionIds) AND t.myId = :pid")
|
||||
@Query("SELECT t FROM ResourceTable t WHERE t.myPartitionIdValue IN (:partitionIds) AND t.myPid.myId = :pid")
|
||||
Optional<ResourceTable> readByPartitionIds(
|
||||
@Param("partitionIds") Collection<Integer> thrValues, @Param("pid") Long theResourceId);
|
||||
|
||||
@Query("SELECT t FROM ResourceTable t WHERE t.myId IN :pids")
|
||||
List<ResourceTable> findAllByIdAndLoadForcedIds(@Param("pids") List<Long> thePids);
|
||||
@Query("SELECT t FROM ResourceTable t WHERE t.myPid IN :pids")
|
||||
List<ResourceTable> findAllByIdAndLoadForcedIds(@Param("pids") List<JpaPid> thePids);
|
||||
|
||||
@Query("SELECT t FROM ResourceTable t where t.myResourceType = :restype and t.myFhirId = :fhirId")
|
||||
Optional<ResourceTable> findByTypeAndFhirId(
|
||||
@Param("restype") String theResourceName, @Param("fhirId") String theFhirId);
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #findById(Object)}
|
||||
*/
|
||||
default Optional<ResourceTable> findById(Long theId) {
|
||||
return findById(JpaPid.fromId(theId));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
*/
|
||||
package ca.uhn.fhir.jpa.dao.data;
|
||||
|
||||
import ca.uhn.fhir.jpa.model.dao.JpaPid;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTag;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
|
@ -28,10 +29,10 @@ import org.springframework.data.repository.query.Param;
|
|||
import java.util.Collection;
|
||||
|
||||
public interface IResourceTagDao extends JpaRepository<ResourceTag, Long>, IHapiFhirJpaRepository {
|
||||
@Query("" + "SELECT t FROM ResourceTag t " + "INNER JOIN FETCH t.myTag td " + "WHERE t.myResourceId in (:pids)")
|
||||
Collection<ResourceTag> findByResourceIds(@Param("pids") Collection<Long> pids);
|
||||
@Query("SELECT t FROM ResourceTag t INNER JOIN FETCH t.myTag td WHERE t.myResource.myPid in (:pids)")
|
||||
Collection<ResourceTag> findByResourceIds(@Param("pids") Collection<JpaPid> pids);
|
||||
|
||||
@Modifying
|
||||
@Query("delete from ResourceTag t WHERE t.myResourceId = :resId")
|
||||
void deleteByResourceId(@Param("resId") Long theResourcePid);
|
||||
@Query("delete from ResourceTag t WHERE t.myResource.myPid = :resId")
|
||||
void deleteByResourceId(@Param("resId") JpaPid theResourcePid);
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
*/
|
||||
package ca.uhn.fhir.jpa.dao.data;
|
||||
|
||||
import ca.uhn.fhir.jpa.model.dao.JpaPid;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.model.entity.SearchParamPresentEntity;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
@ -34,6 +35,6 @@ public interface ISearchParamPresentDao extends JpaRepository<SearchParamPresent
|
|||
List<SearchParamPresentEntity> findAllForResource(@Param("res") ResourceTable theResource);
|
||||
|
||||
@Modifying
|
||||
@Query("delete from SearchParamPresentEntity t WHERE t.myResourcePid = :resid")
|
||||
void deleteByResourceId(@Param("resid") Long theResourcePid);
|
||||
@Query("delete from SearchParamPresentEntity t WHERE t.myResource.myPid = :resid")
|
||||
void deleteByResourceId(@Param("resid") JpaPid theResourcePid);
|
||||
}
|
||||
|
|
|
@ -35,11 +35,13 @@ import java.util.List;
|
|||
|
||||
public interface ISearchResultDao extends JpaRepository<SearchResult, Long>, IHapiFhirJpaRepository {
|
||||
|
||||
@Query(value = "SELECT r.myResourcePid FROM SearchResult r WHERE r.mySearchPid = :search ORDER BY r.myOrder ASC")
|
||||
Slice<Long> findWithSearchPid(@Param("search") Long theSearchPid, Pageable thePage);
|
||||
@Query(
|
||||
value =
|
||||
"SELECT r.myResourcePartitionId,r.myResourcePid FROM SearchResult r WHERE r.mySearchPid = :search ORDER BY r.myOrder ASC")
|
||||
Slice<Object[]> findWithSearchPid(@Param("search") Long theSearchPid, Pageable thePage);
|
||||
|
||||
@Query(value = "SELECT r.myResourcePid FROM SearchResult r WHERE r.mySearchPid = :search")
|
||||
List<Long> findWithSearchPidOrderIndependent(@Param("search") Long theSearchPid);
|
||||
@Query(value = "SELECT r.myResourcePartitionId,r.myResourcePid FROM SearchResult r WHERE r.mySearchPid = :search")
|
||||
List<Object[]> findWithSearchPidOrderIndependent(@Param("search") Long theSearchPid);
|
||||
|
||||
@Modifying
|
||||
@Query("DELETE FROM SearchResult s WHERE s.mySearchPid IN :searchIds")
|
||||
|
@ -62,10 +64,12 @@ public interface ISearchResultDao extends JpaRepository<SearchResult, Long>, IHa
|
|||
* Converts a response from {@link #findWithSearchPid(Long, Pageable)} to
|
||||
* a List of JpaPid objects
|
||||
*/
|
||||
static List<JpaPid> toJpaPidList(List<Long> theArrays) {
|
||||
static List<JpaPid> toJpaPidList(List<Object[]> theArrays) {
|
||||
List<JpaPid> retVal = new ArrayList<>(theArrays.size());
|
||||
for (Long next : theArrays) {
|
||||
retVal.add(JpaPid.fromId(next));
|
||||
for (Object[] next : theArrays) {
|
||||
Integer partitionId = (Integer) next[0];
|
||||
Long resourcePid = (Long) next[1];
|
||||
retVal.add(JpaPid.fromId(resourcePid, partitionId));
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
|
|
@ -20,17 +20,20 @@
|
|||
package ca.uhn.fhir.jpa.dao.data;
|
||||
|
||||
import ca.uhn.fhir.jpa.entity.SubscriptionTable;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.model.entity.IdAndPartitionId;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
|
||||
public interface ISubscriptionTableDao extends JpaRepository<SubscriptionTable, Long>, IHapiFhirJpaRepository {
|
||||
// TODO: We deprecated this entity in 8.0.0 and stopped writing it - Eventually delete it
|
||||
@Deprecated
|
||||
public interface ISubscriptionTableDao
|
||||
extends JpaRepository<SubscriptionTable, IdAndPartitionId>, IHapiFhirJpaRepository {
|
||||
|
||||
@Modifying
|
||||
@Query("DELETE FROM SubscriptionTable t WHERE t.mySubscriptionResource = :subscription ")
|
||||
void deleteAllForSubscription(@Param("subscription") ResourceTable theSubscription);
|
||||
@Query("DELETE FROM SubscriptionTable t WHERE t.myResId = :res_id ")
|
||||
void deleteAllForSubscription(@Param("res_id") Long theSubscriptionResourceId);
|
||||
|
||||
@Query("SELECT t FROM SubscriptionTable t WHERE t.myResId = :pid")
|
||||
SubscriptionTable findOneByResourcePid(@Param("pid") Long theId);
|
||||
|
|
|
@ -20,20 +20,29 @@
|
|||
package ca.uhn.fhir.jpa.dao.data;
|
||||
|
||||
import ca.uhn.fhir.jpa.entity.TermCodeSystem;
|
||||
import ca.uhn.fhir.jpa.model.dao.JpaPid;
|
||||
import ca.uhn.fhir.jpa.model.entity.IdAndPartitionId;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public interface ITermCodeSystemDao extends JpaRepository<TermCodeSystem, Long>, IHapiFhirJpaRepository {
|
||||
public interface ITermCodeSystemDao extends JpaRepository<TermCodeSystem, IdAndPartitionId>, IHapiFhirJpaRepository {
|
||||
|
||||
@Query("SELECT cs FROM TermCodeSystem cs WHERE cs.myCodeSystemUri = :code_system_uri")
|
||||
TermCodeSystem findByCodeSystemUri(@Param("code_system_uri") String theCodeSystemUri);
|
||||
|
||||
@Query("SELECT cs FROM TermCodeSystem cs WHERE cs.myResourcePid = :resource_pid")
|
||||
TermCodeSystem findByResourcePid(@Param("resource_pid") Long theResourcePid);
|
||||
@Query("SELECT cs FROM TermCodeSystem cs WHERE cs.myResource.myPid = :resource_pid")
|
||||
TermCodeSystem findByResourcePid(@Param("resource_pid") JpaPid theResourcePid);
|
||||
|
||||
@Query("SELECT cs FROM TermCodeSystem cs WHERE cs.myCurrentVersion.myId = :csv_pid")
|
||||
Optional<TermCodeSystem> findWithCodeSystemVersionAsCurrentVersion(@Param("csv_pid") Long theCodeSystemVersionPid);
|
||||
|
||||
/**
|
||||
* // TODO: JA2 Use partitioned query here
|
||||
*/
|
||||
@Deprecated
|
||||
@Query("SELECT cs FROM TermCodeSystem cs WHERE cs.myId = :pid")
|
||||
Optional<TermCodeSystem> findByPid(@Param("pid") long thePid);
|
||||
}
|
||||
|
|
|
@ -21,21 +21,29 @@ package ca.uhn.fhir.jpa.dao.data;
|
|||
|
||||
import ca.uhn.fhir.jpa.entity.TermCodeSystem;
|
||||
import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion;
|
||||
import ca.uhn.fhir.jpa.model.dao.JpaPid;
|
||||
import ca.uhn.fhir.jpa.model.entity.IdAndPartitionId;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface ITermCodeSystemVersionDao extends JpaRepository<TermCodeSystemVersion, Long>, IHapiFhirJpaRepository {
|
||||
public interface ITermCodeSystemVersionDao
|
||||
extends JpaRepository<TermCodeSystemVersion, IdAndPartitionId>, IHapiFhirJpaRepository {
|
||||
|
||||
@Modifying
|
||||
@Query("DELETE FROM TermCodeSystemVersion csv WHERE csv.myCodeSystem = :cs")
|
||||
void deleteForCodeSystem(@Param("cs") TermCodeSystem theCodeSystem);
|
||||
|
||||
@Query("SELECT myId FROM TermCodeSystemVersion WHERE myCodeSystemPid = :codesystem_pid order by myId")
|
||||
List<Long> findSortedPidsByCodeSystemPid(@Param("codesystem_pid") Long theCodeSystemPid);
|
||||
/**
|
||||
* @return Return type is [PartitionId,Pid]
|
||||
*/
|
||||
@Query(
|
||||
"SELECT t.myPartitionIdValue, t.myId FROM TermCodeSystemVersion t WHERE t.myCodeSystemPid = :codesystem_pid order by t.myId")
|
||||
List<Object[]> findSortedPidsByCodeSystemPid(@Param("codesystem_pid") Long theCodeSystemPid);
|
||||
|
||||
@Query(
|
||||
"SELECT cs FROM TermCodeSystemVersion cs WHERE cs.myCodeSystemPid = :codesystem_pid AND cs.myCodeSystemVersionId = :codesystem_version_id")
|
||||
|
@ -43,9 +51,8 @@ public interface ITermCodeSystemVersionDao extends JpaRepository<TermCodeSystemV
|
|||
@Param("codesystem_pid") Long theCodeSystemPid,
|
||||
@Param("codesystem_version_id") String theCodeSystemVersionId);
|
||||
|
||||
@Query(
|
||||
"SELECT tcsv FROM TermCodeSystemVersion tcsv INNER JOIN FETCH TermCodeSystem tcs on tcs.myPid = tcsv.myCodeSystemPid "
|
||||
+ "WHERE tcs.myCodeSystemUri = :code_system_uri AND tcsv.myCodeSystemVersionId = :codesystem_version_id")
|
||||
@Query("SELECT tcsv FROM TermCodeSystemVersion tcsv INNER JOIN FETCH TermCodeSystem tcs on tcs = tcsv.myCodeSystem "
|
||||
+ "WHERE tcs.myCodeSystemUri = :code_system_uri AND tcsv.myCodeSystemVersionId = :codesystem_version_id")
|
||||
TermCodeSystemVersion findByCodeSystemUriAndVersion(
|
||||
@Param("code_system_uri") String theCodeSystemUri,
|
||||
@Param("codesystem_version_id") String theCodeSystemVersionId);
|
||||
|
@ -54,11 +61,18 @@ public interface ITermCodeSystemVersionDao extends JpaRepository<TermCodeSystemV
|
|||
"SELECT cs FROM TermCodeSystemVersion cs WHERE cs.myCodeSystemPid = :codesystem_pid AND cs.myCodeSystemVersionId IS NULL")
|
||||
TermCodeSystemVersion findByCodeSystemPidVersionIsNull(@Param("codesystem_pid") Long theCodeSystemPid);
|
||||
|
||||
@Query("SELECT cs FROM TermCodeSystemVersion cs WHERE cs.myResourcePid = :resource_id")
|
||||
List<TermCodeSystemVersion> findByCodeSystemResourcePid(@Param("resource_id") Long theCodeSystemResourcePid);
|
||||
@Query("SELECT cs FROM TermCodeSystemVersion cs WHERE cs.myResource.myPid = :resource_id")
|
||||
List<TermCodeSystemVersion> findByCodeSystemResourcePid(@Param("resource_id") JpaPid theCodeSystemResourcePid);
|
||||
|
||||
@Query(
|
||||
"SELECT cs FROM TermCodeSystemVersion cs WHERE cs.myCodeSystemHavingThisVersionAsCurrentVersionIfAny.myResource.myId = :resource_id")
|
||||
@Query("SELECT csv FROM TermCodeSystemVersion csv " + "JOIN TermCodeSystem cs ON (cs.myCurrentVersion = csv) "
|
||||
+ "WHERE cs.myResource.myPid.myId = :resource_id")
|
||||
TermCodeSystemVersion findCurrentVersionForCodeSystemResourcePid(
|
||||
@Param("resource_id") Long theCodeSystemResourcePid);
|
||||
|
||||
/**
|
||||
* // TODO: JA2 Use partitioned query here
|
||||
*/
|
||||
@Deprecated
|
||||
@Query("SELECT cs FROM TermCodeSystemVersion cs WHERE cs.myId = :pid")
|
||||
Optional<TermCodeSystemVersion> findByPid(@Param("pid") long theVersionPid);
|
||||
}
|
||||
|
|
|
@ -31,10 +31,10 @@ import org.springframework.data.repository.query.Param;
|
|||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface ITermConceptDao extends JpaRepository<TermConcept, Long>, IHapiFhirJpaRepository {
|
||||
public interface ITermConceptDao extends JpaRepository<TermConcept, TermConcept.TermConceptPk>, IHapiFhirJpaRepository {
|
||||
|
||||
@Query("SELECT t FROM TermConcept t " + "LEFT JOIN FETCH t.myDesignations d " + "WHERE t.myId IN :pids")
|
||||
List<TermConcept> fetchConceptsAndDesignationsByPid(@Param("pids") List<Long> thePids);
|
||||
List<TermConcept> fetchConceptsAndDesignationsByPid(@Param("pids") List<TermConcept.TermConceptPk> thePids);
|
||||
|
||||
@Query("SELECT t FROM TermConcept t " + "LEFT JOIN FETCH t.myDesignations d "
|
||||
+ "WHERE t.myCodeSystemVersionPid = :pid")
|
||||
|
|
|
@ -20,13 +20,14 @@
|
|||
package ca.uhn.fhir.jpa.dao.data;
|
||||
|
||||
import ca.uhn.fhir.jpa.entity.TermConceptDesignation;
|
||||
import ca.uhn.fhir.jpa.model.entity.IdAndPartitionId;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
|
||||
public interface ITermConceptDesignationDao
|
||||
extends JpaRepository<TermConceptDesignation, Long>, IHapiFhirJpaRepository {
|
||||
extends JpaRepository<TermConceptDesignation, IdAndPartitionId>, IHapiFhirJpaRepository {
|
||||
|
||||
@Modifying
|
||||
@Query("DELETE FROM TermConceptDesignation WHERE myCodeSystemVersion.myId = :csv_pid")
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
package ca.uhn.fhir.jpa.dao.data;
|
||||
|
||||
import ca.uhn.fhir.jpa.entity.TermConceptMap;
|
||||
import ca.uhn.fhir.jpa.model.entity.IdAndPartitionId;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
|
@ -29,7 +30,7 @@ import org.springframework.data.repository.query.Param;
|
|||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface ITermConceptMapDao extends JpaRepository<TermConceptMap, Long>, IHapiFhirJpaRepository {
|
||||
public interface ITermConceptMapDao extends JpaRepository<TermConceptMap, IdAndPartitionId>, IHapiFhirJpaRepository {
|
||||
@Query("DELETE FROM TermConceptMap cm WHERE cm.myId = :pid")
|
||||
@Modifying
|
||||
void deleteTermConceptMapById(@Param("pid") Long theId);
|
||||
|
@ -48,7 +49,7 @@ public interface ITermConceptMapDao extends JpaRepository<TermConceptMap, Long>,
|
|||
// Note that last updated version is considered current version.
|
||||
@Query(
|
||||
value =
|
||||
"SELECT cm FROM TermConceptMap cm INNER JOIN ResourceTable r ON r.myId = cm.myResourcePid WHERE cm.myUrl = :url ORDER BY r.myUpdated DESC")
|
||||
"SELECT cm FROM TermConceptMap cm INNER JOIN ResourceTable r ON r = cm.myResource WHERE cm.myUrl = :url ORDER BY r.myUpdated DESC")
|
||||
List<TermConceptMap> getTermConceptMapEntitiesByUrlOrderByMostRecentUpdate(
|
||||
Pageable thePage, @Param("url") String theUrl);
|
||||
|
||||
|
|
|
@ -20,12 +20,14 @@
|
|||
package ca.uhn.fhir.jpa.dao.data;
|
||||
|
||||
import ca.uhn.fhir.jpa.entity.TermConceptMapGroup;
|
||||
import ca.uhn.fhir.jpa.model.entity.IdAndPartitionId;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
|
||||
public interface ITermConceptMapGroupDao extends JpaRepository<TermConceptMapGroup, Long>, IHapiFhirJpaRepository {
|
||||
public interface ITermConceptMapGroupDao
|
||||
extends JpaRepository<TermConceptMapGroup, IdAndPartitionId>, IHapiFhirJpaRepository {
|
||||
@Query("DELETE FROM TermConceptMapGroup g WHERE g.myId = :pid")
|
||||
@Modifying
|
||||
void deleteTermConceptMapGroupById(@Param("pid") Long theId);
|
||||
|
|
|
@ -20,13 +20,14 @@
|
|||
package ca.uhn.fhir.jpa.dao.data;
|
||||
|
||||
import ca.uhn.fhir.jpa.entity.TermConceptMapGroupElement;
|
||||
import ca.uhn.fhir.jpa.model.entity.IdAndPartitionId;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
|
||||
public interface ITermConceptMapGroupElementDao
|
||||
extends JpaRepository<TermConceptMapGroupElement, Long>, IHapiFhirJpaRepository {
|
||||
extends JpaRepository<TermConceptMapGroupElement, IdAndPartitionId>, IHapiFhirJpaRepository {
|
||||
@Query("DELETE FROM TermConceptMapGroupElement e WHERE e.myId = :pid")
|
||||
@Modifying
|
||||
void deleteTermConceptMapGroupElementById(@Param("pid") Long theId);
|
||||
|
|
|
@ -20,13 +20,14 @@
|
|||
package ca.uhn.fhir.jpa.dao.data;
|
||||
|
||||
import ca.uhn.fhir.jpa.entity.TermConceptMapGroupElementTarget;
|
||||
import ca.uhn.fhir.jpa.model.entity.IdAndPartitionId;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
|
||||
public interface ITermConceptMapGroupElementTargetDao
|
||||
extends JpaRepository<TermConceptMapGroupElementTarget, Long>, IHapiFhirJpaRepository {
|
||||
extends JpaRepository<TermConceptMapGroupElementTarget, IdAndPartitionId>, IHapiFhirJpaRepository {
|
||||
@Query("DELETE FROM TermConceptMapGroupElementTarget t WHERE t.myId = :pid")
|
||||
@Modifying
|
||||
void deleteTermConceptMapGroupElementTargetById(@Param("pid") Long theId);
|
||||
|
|
|
@ -28,7 +28,8 @@ import org.springframework.data.repository.query.Param;
|
|||
import java.util.Collection;
|
||||
|
||||
public interface ITermConceptParentChildLinkDao
|
||||
extends JpaRepository<TermConceptParentChildLink, Long>, IHapiFhirJpaRepository {
|
||||
extends JpaRepository<TermConceptParentChildLink, TermConceptParentChildLink.TermConceptParentChildLinkPk>,
|
||||
IHapiFhirJpaRepository {
|
||||
|
||||
@Query("SELECT t.myParentPid FROM TermConceptParentChildLink t WHERE t.myChildPid = :child_pid")
|
||||
Collection<Long> findAllWithChild(@Param("child_pid") Long theConceptPid);
|
||||
|
|
|
@ -20,12 +20,14 @@
|
|||
package ca.uhn.fhir.jpa.dao.data;
|
||||
|
||||
import ca.uhn.fhir.jpa.entity.TermConceptProperty;
|
||||
import ca.uhn.fhir.jpa.model.entity.IdAndPartitionId;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
|
||||
public interface ITermConceptPropertyDao extends JpaRepository<TermConceptProperty, Long>, IHapiFhirJpaRepository {
|
||||
public interface ITermConceptPropertyDao
|
||||
extends JpaRepository<TermConceptProperty, IdAndPartitionId>, IHapiFhirJpaRepository {
|
||||
|
||||
@Modifying
|
||||
@Query("DELETE FROM TermConceptProperty WHERE myCodeSystemVersion.myId = :cs_pid")
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
package ca.uhn.fhir.jpa.dao.data;
|
||||
|
||||
import ca.uhn.fhir.jpa.entity.TermValueSetConcept;
|
||||
import ca.uhn.fhir.jpa.model.entity.IdAndPartitionId;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
|
@ -29,7 +30,8 @@ import org.springframework.data.repository.query.Param;
|
|||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface ITermValueSetConceptDao extends JpaRepository<TermValueSetConcept, Long>, IHapiFhirJpaRepository {
|
||||
public interface ITermValueSetConceptDao
|
||||
extends JpaRepository<TermValueSetConcept, IdAndPartitionId>, IHapiFhirJpaRepository {
|
||||
|
||||
@Query("SELECT COUNT(*) FROM TermValueSetConcept vsc WHERE vsc.myValueSetPid = :pid")
|
||||
Integer countByTermValueSetId(@Param("pid") Long theValueSetId);
|
||||
|
|
|
@ -20,13 +20,14 @@
|
|||
package ca.uhn.fhir.jpa.dao.data;
|
||||
|
||||
import ca.uhn.fhir.jpa.entity.TermValueSetConceptDesignation;
|
||||
import ca.uhn.fhir.jpa.model.entity.IdAndPartitionId;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
|
||||
public interface ITermValueSetConceptDesignationDao
|
||||
extends JpaRepository<TermValueSetConceptDesignation, Long>, IHapiFhirJpaRepository {
|
||||
extends JpaRepository<TermValueSetConceptDesignation, IdAndPartitionId>, IHapiFhirJpaRepository {
|
||||
|
||||
@Query("SELECT COUNT(vscd) FROM TermValueSetConceptDesignation vscd WHERE vscd.myValueSetPid = :pid")
|
||||
Integer countByTermValueSetId(@Param("pid") Long theValueSetId);
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
package ca.uhn.fhir.jpa.dao.data;
|
||||
|
||||
import ca.uhn.fhir.jpa.entity.TermValueSetConceptView;
|
||||
import ca.uhn.fhir.jpa.model.entity.IdAndPartitionId;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
|
@ -27,7 +28,7 @@ import org.springframework.data.repository.query.Param;
|
|||
import java.util.List;
|
||||
|
||||
public interface ITermValueSetConceptViewDao
|
||||
extends JpaRepository<TermValueSetConceptView, Long>, IHapiFhirJpaRepository {
|
||||
extends JpaRepository<TermValueSetConceptView, IdAndPartitionId>, IHapiFhirJpaRepository {
|
||||
|
||||
@Query(
|
||||
"SELECT v FROM TermValueSetConceptView v WHERE v.myConceptValueSetPid = :pid AND v.myConceptOrder >= :from AND v.myConceptOrder < :to ORDER BY v.myConceptOrder")
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
package ca.uhn.fhir.jpa.dao.data;
|
||||
|
||||
import ca.uhn.fhir.jpa.entity.TermValueSetConceptViewOracle;
|
||||
import ca.uhn.fhir.jpa.model.entity.IdAndPartitionId;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
|
@ -27,7 +28,7 @@ import org.springframework.data.repository.query.Param;
|
|||
import java.util.List;
|
||||
|
||||
public interface ITermValueSetConceptViewOracleDao
|
||||
extends JpaRepository<TermValueSetConceptViewOracle, Long>, IHapiFhirJpaRepository {
|
||||
extends JpaRepository<TermValueSetConceptViewOracle, IdAndPartitionId>, IHapiFhirJpaRepository {
|
||||
@Query(
|
||||
"SELECT v FROM TermValueSetConceptViewOracle v WHERE v.myConceptValueSetPid = :pid AND v.myConceptOrder >= :from AND v.myConceptOrder < :to ORDER BY v.myConceptOrder")
|
||||
List<TermValueSetConceptViewOracle> findByTermValueSetId(
|
||||
|
|
|
@ -21,6 +21,8 @@ package ca.uhn.fhir.jpa.dao.data;
|
|||
|
||||
import ca.uhn.fhir.jpa.entity.TermValueSet;
|
||||
import ca.uhn.fhir.jpa.entity.TermValueSetPreExpansionStatusEnum;
|
||||
import ca.uhn.fhir.jpa.model.dao.JpaPid;
|
||||
import ca.uhn.fhir.jpa.model.entity.IdAndPartitionId;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Slice;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
@ -30,10 +32,10 @@ import org.springframework.data.repository.query.Param;
|
|||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface ITermValueSetDao extends JpaRepository<TermValueSet, Long>, IHapiFhirJpaRepository {
|
||||
public interface ITermValueSetDao extends JpaRepository<TermValueSet, IdAndPartitionId>, IHapiFhirJpaRepository {
|
||||
|
||||
@Query("SELECT vs FROM TermValueSet vs WHERE vs.myResourcePid = :resource_pid")
|
||||
Optional<TermValueSet> findByResourcePid(@Param("resource_pid") Long theResourcePid);
|
||||
@Query("SELECT vs FROM TermValueSet vs WHERE vs.myResource.myPid = :resource_pid")
|
||||
Optional<TermValueSet> findByResourcePid(@Param("resource_pid") JpaPid theResourcePid);
|
||||
|
||||
// Keeping for backwards compatibility but recommend using findTermValueSetByUrlAndNullVersion instead.
|
||||
@Deprecated
|
||||
|
@ -46,7 +48,7 @@ public interface ITermValueSetDao extends JpaRepository<TermValueSet, Long>, IHa
|
|||
|
||||
@Query(
|
||||
value =
|
||||
"SELECT vs FROM TermValueSet vs INNER JOIN ResourceTable r ON r.myId = vs.myResourcePid WHERE vs.myUrl = :url ORDER BY r.myUpdated DESC")
|
||||
"SELECT vs FROM TermValueSet vs INNER JOIN ResourceTable r ON r = vs.myResource WHERE vs.myUrl = :url ORDER BY r.myUpdated DESC")
|
||||
List<TermValueSet> findTermValueSetByUrl(Pageable thePage, @Param("url") String theUrl);
|
||||
|
||||
/**
|
||||
|
|
|
@ -57,7 +57,7 @@ public class IResourceTableDaoImpl implements IForcedIdQueries {
|
|||
public Collection<Object[]> findAndResolveByForcedIdWithNoType(
|
||||
String theResourceType, Collection<String> theForcedIds, boolean theExcludeDeleted) {
|
||||
String query =
|
||||
"SELECT t.myResourceType, t.myId, t.myFhirId, t.myDeleted, t.myPartitionIdValue, t.myPartitionDateValue "
|
||||
"SELECT t.myResourceType, t.myPid.myId, t.myFhirId, t.myDeleted, t.myPartitionIdValue, t.myPartitionDateValue "
|
||||
+ "FROM ResourceTable t "
|
||||
+ "WHERE t.myResourceType = :resource_type AND t.myFhirId IN ( :forced_id )";
|
||||
|
||||
|
@ -84,7 +84,7 @@ public class IResourceTableDaoImpl implements IForcedIdQueries {
|
|||
Collection<Integer> thePartitionId,
|
||||
boolean theExcludeDeleted) {
|
||||
String query =
|
||||
"SELECT t.myResourceType, t.myId, t.myFhirId, t.myDeleted, t.myPartitionIdValue, t.myPartitionDateValue "
|
||||
"SELECT t.myResourceType, t.myPid.myId, t.myFhirId, t.myDeleted, t.myPartitionIdValue, t.myPartitionDateValue "
|
||||
+ "FROM ResourceTable t "
|
||||
+ "WHERE t.myResourceType = :resource_type AND t.myFhirId IN ( :forced_id ) AND t.myPartitionIdValue IN ( :partition_id )";
|
||||
|
||||
|
@ -110,7 +110,7 @@ public class IResourceTableDaoImpl implements IForcedIdQueries {
|
|||
String theResourceType, Collection<String> theForcedIds, boolean theExcludeDeleted) {
|
||||
// we fetch myPartitionIdValue and myPartitionDateValue for resultSet processing consistency
|
||||
String query =
|
||||
"SELECT t.myResourceType, t.myId, t.myFhirId, t.myDeleted, t.myPartitionIdValue, t.myPartitionDateValue "
|
||||
"SELECT t.myResourceType, t.myPid.myId, t.myFhirId, t.myDeleted, t.myPartitionIdValue, t.myPartitionDateValue "
|
||||
+ "FROM ResourceTable t "
|
||||
+ "WHERE t.myResourceType = :resource_type AND t.myFhirId IN ( :forced_id ) AND t.myPartitionIdValue IS NULL";
|
||||
|
||||
|
@ -137,7 +137,7 @@ public class IResourceTableDaoImpl implements IForcedIdQueries {
|
|||
List<Integer> thePartitionIdsWithoutDefault,
|
||||
boolean theExcludeDeleted) {
|
||||
String query =
|
||||
"SELECT t.myResourceType, t.myId, t.myFhirId, t.myDeleted, t.myPartitionIdValue, t.myPartitionDateValue "
|
||||
"SELECT t.myResourceType, t.myPid.myId, t.myFhirId, t.myDeleted, t.myPartitionIdValue, t.myPartitionDateValue "
|
||||
+ "FROM ResourceTable t "
|
||||
+ "WHERE t.myResourceType = :resource_type AND t.myFhirId IN ( :forced_id ) AND (t.myPartitionIdValue IS NULL OR t.myPartitionIdValue IN ( :partition_id ))";
|
||||
|
||||
|
|
|
@ -40,32 +40,18 @@ public class FhirResourceDaoSubscriptionDstu3 extends BaseHapiFhirResourceDao<Su
|
|||
@Autowired
|
||||
private ISubscriptionTableDao mySubscriptionTableDao;
|
||||
|
||||
private void createSubscriptionTable(ResourceTable theEntity, Subscription theSubscription) {
|
||||
SubscriptionTable subscriptionEntity = new SubscriptionTable();
|
||||
subscriptionEntity.setCreated(new Date());
|
||||
subscriptionEntity.setSubscriptionResource(theEntity);
|
||||
myEntityManager.persist(subscriptionEntity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getSubscriptionTablePidForSubscriptionResource(
|
||||
IIdType theId, RequestDetails theRequest, TransactionDetails theTransactionDetails) {
|
||||
ResourceTable entity = readEntityLatestVersion(theId, theRequest, theTransactionDetails);
|
||||
SubscriptionTable table = mySubscriptionTableDao.findOneByResourcePid(entity.getId());
|
||||
SubscriptionTable table =
|
||||
mySubscriptionTableDao.findOneByResourcePid(entity.getId().getId());
|
||||
if (table == null) {
|
||||
return null;
|
||||
}
|
||||
return table.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void postPersist(
|
||||
ResourceTable theEntity, Subscription theSubscription, RequestDetails theRequestDetails) {
|
||||
super.postPersist(theEntity, theSubscription, theRequestDetails);
|
||||
|
||||
createSubscriptionTable(theEntity, theSubscription);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceTable updateEntity(
|
||||
RequestDetails theRequest,
|
||||
|
@ -89,7 +75,8 @@ public class FhirResourceDaoSubscriptionDstu3 extends BaseHapiFhirResourceDao<Su
|
|||
theCreateNewHistoryEntry);
|
||||
|
||||
if (theDeletedTimestampOrNull != null) {
|
||||
mySubscriptionTableDao.deleteAllForSubscription((ResourceTable) theEntity);
|
||||
mySubscriptionTableDao.deleteAllForSubscription(
|
||||
((ResourceTable) theEntity).getResourceId().getId());
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
|
|
@ -70,6 +70,7 @@ import ca.uhn.fhir.jpa.model.entity.ResourceTag;
|
|||
import ca.uhn.fhir.jpa.model.entity.SearchParamPresentEntity;
|
||||
import ca.uhn.fhir.jpa.model.entity.TagDefinition;
|
||||
import ca.uhn.fhir.jpa.partition.IRequestPartitionHelperSvc;
|
||||
import ca.uhn.fhir.jpa.search.builder.SearchBuilder;
|
||||
import ca.uhn.fhir.jpa.util.MemoryCacheService;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.server.provider.ProviderConstants;
|
||||
|
@ -92,7 +93,10 @@ import org.slf4j.LoggerFactory;
|
|||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.util.comparator.Comparators;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
@ -308,25 +312,59 @@ public class ExpungeEverythingService implements IExpungeEverythingService {
|
|||
Metamodel metamodel = myEntityManager.getMetamodel();
|
||||
EntityType<T> entity = metamodel.entity(theEntityType);
|
||||
Set<SingularAttribute<? super T, ?>> singularAttributes = entity.getSingularAttributes();
|
||||
String idProperty = null;
|
||||
List<String> idProperty = new ArrayList<>();
|
||||
for (SingularAttribute<? super T, ?> singularAttribute : singularAttributes) {
|
||||
if (singularAttribute.isId()) {
|
||||
idProperty = singularAttribute.getName();
|
||||
break;
|
||||
idProperty.add(singularAttribute.getName());
|
||||
}
|
||||
}
|
||||
idProperty.sort(Comparators.comparable());
|
||||
String idPropertyNames = String.join(",", idProperty);
|
||||
|
||||
Query nativeQuery = myEntityManager.createQuery(
|
||||
"SELECT " + idProperty + " FROM " + theEntityType.getSimpleName());
|
||||
nativeQuery.setMaxResults(800);
|
||||
List pids = nativeQuery.getResultList();
|
||||
"SELECT (" + idPropertyNames + ") FROM " + theEntityType.getSimpleName());
|
||||
|
||||
if (!pids.isEmpty()) {
|
||||
nativeQuery = myEntityManager.createQuery("DELETE FROM " + theEntityType.getSimpleName()
|
||||
+ " WHERE " + idProperty + " IN (:pids)");
|
||||
nativeQuery.setParameter("pids", pids);
|
||||
nativeQuery.executeUpdate();
|
||||
// Each ID is 2 parameters in DB partition mode, so this
|
||||
// is the maximum we should allow
|
||||
nativeQuery.setMaxResults(SearchBuilder.getMaximumPageSize() / 2);
|
||||
|
||||
List pids = nativeQuery.getResultList();
|
||||
if (pids.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
StringBuilder deleteBuilder = new StringBuilder();
|
||||
deleteBuilder.append("DELETE FROM ");
|
||||
deleteBuilder.append(theEntityType.getSimpleName());
|
||||
deleteBuilder.append(" WHERE (");
|
||||
deleteBuilder.append(idPropertyNames);
|
||||
deleteBuilder.append(") IN ");
|
||||
if (idProperty.size() > 1) {
|
||||
deleteBuilder.append('(');
|
||||
for (Iterator<Object> iter = pids.iterator(); iter.hasNext(); ) {
|
||||
Object[] pid = (Object[]) iter.next();
|
||||
deleteBuilder.append('(');
|
||||
for (int i = 0; i < pid.length; i++) {
|
||||
if (i > 0) {
|
||||
deleteBuilder.append(',');
|
||||
}
|
||||
deleteBuilder.append(pid[i]);
|
||||
}
|
||||
deleteBuilder.append(')');
|
||||
if (iter.hasNext()) {
|
||||
deleteBuilder.append(',');
|
||||
}
|
||||
}
|
||||
deleteBuilder.append(')');
|
||||
} else {
|
||||
deleteBuilder.append("(:pids)");
|
||||
}
|
||||
String deleteSql = deleteBuilder.toString();
|
||||
nativeQuery = myEntityManager.createQuery(deleteSql);
|
||||
if (idProperty.size() == 1) {
|
||||
nativeQuery.setParameter("pids", pids);
|
||||
}
|
||||
nativeQuery.executeUpdate();
|
||||
return pids.size();
|
||||
});
|
||||
|
||||
|
|
|
@ -24,8 +24,6 @@ import ca.uhn.fhir.interceptor.api.HookParams;
|
|||
import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
|
||||
import ca.uhn.fhir.interceptor.api.Pointcut;
|
||||
import ca.uhn.fhir.jpa.api.config.JpaStorageSettings;
|
||||
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
|
||||
import ca.uhn.fhir.jpa.api.svc.IIdHelperService;
|
||||
import ca.uhn.fhir.jpa.dao.IJpaStorageResourceParser;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceHistoryProvenanceDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceHistoryTableDao;
|
||||
|
@ -47,6 +45,7 @@ import ca.uhn.fhir.jpa.dao.data.ISearchParamPresentDao;
|
|||
import ca.uhn.fhir.jpa.model.dao.JpaPid;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceHistoryProvenanceEntity;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceHistoryTable;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceHistoryTablePk;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.util.MemoryCacheService;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
|
@ -76,7 +75,7 @@ import java.util.Optional;
|
|||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
@Service
|
||||
public class JpaResourceExpungeService implements IResourceExpungeService<JpaPid> {
|
||||
public class JpaResourceExpungeService implements IResourceExpungeService<JpaPid, ResourceHistoryTablePk> {
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(JpaResourceExpungeService.class);
|
||||
|
||||
@Autowired
|
||||
|
@ -121,18 +120,12 @@ public class JpaResourceExpungeService implements IResourceExpungeService<JpaPid
|
|||
@Autowired
|
||||
private IResourceTagDao myResourceTagDao;
|
||||
|
||||
@Autowired
|
||||
private IIdHelperService myIdHelperService;
|
||||
|
||||
@Autowired
|
||||
private IResourceHistoryTagDao myResourceHistoryTagDao;
|
||||
|
||||
@Autowired
|
||||
private IInterceptorBroadcaster myInterceptorBroadcaster;
|
||||
|
||||
@Autowired
|
||||
private DaoRegistry myDaoRegistry;
|
||||
|
||||
@Autowired
|
||||
private IResourceHistoryProvenanceDao myResourceHistoryProvenanceTableDao;
|
||||
|
||||
|
@ -150,20 +143,20 @@ public class JpaResourceExpungeService implements IResourceExpungeService<JpaPid
|
|||
|
||||
@Override
|
||||
@Transactional
|
||||
public List<JpaPid> findHistoricalVersionsOfNonDeletedResources(
|
||||
public List<ResourceHistoryTablePk> findHistoricalVersionsOfNonDeletedResources(
|
||||
String theResourceName, JpaPid theJpaPid, int theRemainingCount) {
|
||||
if (isEmptyQuery(theRemainingCount)) {
|
||||
return Collections.EMPTY_LIST;
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
Pageable page = PageRequest.of(0, theRemainingCount);
|
||||
|
||||
Slice<Long> ids;
|
||||
Slice<ResourceHistoryTablePk> ids;
|
||||
if (theJpaPid != null && theJpaPid.getId() != null) {
|
||||
if (theJpaPid.getVersion() != null) {
|
||||
ids = toSlice(myResourceHistoryTableDao.findForIdAndVersion(theJpaPid.getId(), theJpaPid.getVersion()));
|
||||
ids = toSlice(myResourceHistoryTableDao.findForIdAndVersion(theJpaPid.toFk(), theJpaPid.getVersion()));
|
||||
} else {
|
||||
ids = myResourceHistoryTableDao.findIdsOfPreviousVersionsOfResourceId(page, theJpaPid.getId());
|
||||
ids = myResourceHistoryTableDao.findIdsOfPreviousVersionsOfResourceId(page, theJpaPid);
|
||||
}
|
||||
} else {
|
||||
if (theResourceName != null) {
|
||||
|
@ -173,7 +166,7 @@ public class JpaResourceExpungeService implements IResourceExpungeService<JpaPid
|
|||
}
|
||||
}
|
||||
|
||||
return JpaPid.fromLongList(ids.getContent());
|
||||
return ids.getContent();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -181,11 +174,11 @@ public class JpaResourceExpungeService implements IResourceExpungeService<JpaPid
|
|||
public List<JpaPid> findHistoricalVersionsOfDeletedResources(
|
||||
String theResourceName, JpaPid theResourceId, int theRemainingCount) {
|
||||
if (isEmptyQuery(theRemainingCount)) {
|
||||
return Collections.EMPTY_LIST;
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
Pageable page = PageRequest.of(0, theRemainingCount);
|
||||
Slice<Long> ids;
|
||||
Slice<JpaPid> ids;
|
||||
if (theResourceId != null) {
|
||||
ids = myResourceTableDao.findIdsOfDeletedResourcesOfType(page, theResourceId.getId(), theResourceName);
|
||||
ourLog.info(
|
||||
|
@ -202,7 +195,7 @@ public class JpaResourceExpungeService implements IResourceExpungeService<JpaPid
|
|||
ourLog.info("Expunging {} deleted resources (all types)", ids.getNumberOfElements());
|
||||
}
|
||||
}
|
||||
return JpaPid.fromLongList(ids.getContent());
|
||||
return ids.getContent();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -210,7 +203,7 @@ public class JpaResourceExpungeService implements IResourceExpungeService<JpaPid
|
|||
public void expungeCurrentVersionOfResources(
|
||||
RequestDetails theRequestDetails, List<JpaPid> theResourceIds, AtomicInteger theRemainingCount) {
|
||||
for (JpaPid next : theResourceIds) {
|
||||
expungeCurrentVersionOfResource(theRequestDetails, (next).getId(), theRemainingCount);
|
||||
expungeCurrentVersionOfResource(theRequestDetails, next, theRemainingCount);
|
||||
if (expungeLimitReached(theRemainingCount)) {
|
||||
return;
|
||||
}
|
||||
|
@ -232,7 +225,9 @@ public class JpaResourceExpungeService implements IResourceExpungeService<JpaPid
|
|||
}
|
||||
|
||||
private void expungeHistoricalVersion(
|
||||
RequestDetails theRequestDetails, Long theNextVersionId, AtomicInteger theRemainingCount) {
|
||||
RequestDetails theRequestDetails,
|
||||
ResourceHistoryTablePk theNextVersionId,
|
||||
AtomicInteger theRemainingCount) {
|
||||
ResourceHistoryTable version =
|
||||
myResourceHistoryTableDao.findById(theNextVersionId).orElseThrow(IllegalArgumentException::new);
|
||||
IdDt id = version.getIdDt();
|
||||
|
@ -242,7 +237,7 @@ public class JpaResourceExpungeService implements IResourceExpungeService<JpaPid
|
|||
|
||||
if (myStorageSettings.isAccessMetaSourceInformationFromProvenanceTable()) {
|
||||
Optional<ResourceHistoryProvenanceEntity> provenanceOpt =
|
||||
myResourceHistoryProvenanceTableDao.findById(theNextVersionId);
|
||||
myResourceHistoryProvenanceTableDao.findById(theNextVersionId.asIdAndPartitionId());
|
||||
provenanceOpt.ifPresent(entity -> myResourceHistoryProvenanceTableDao.deleteByPid(entity.getId()));
|
||||
}
|
||||
|
||||
|
@ -277,9 +272,7 @@ public class JpaResourceExpungeService implements IResourceExpungeService<JpaPid
|
|||
@Transactional
|
||||
public void expungeHistoricalVersionsOfIds(
|
||||
RequestDetails theRequestDetails, List<JpaPid> theResourceIds, AtomicInteger theRemainingCount) {
|
||||
List<Long> pids = JpaPid.toLongList(theResourceIds);
|
||||
|
||||
List<ResourceTable> resourcesToDelete = myResourceTableDao.findAllByIdAndLoadForcedIds(pids);
|
||||
List<ResourceTable> resourcesToDelete = myResourceTableDao.findAllByIdAndLoadForcedIds(theResourceIds);
|
||||
for (ResourceTable next : resourcesToDelete) {
|
||||
expungeHistoricalVersionsOfId(theRequestDetails, next, theRemainingCount);
|
||||
if (expungeLimitReached(theRemainingCount)) {
|
||||
|
@ -291,9 +284,11 @@ public class JpaResourceExpungeService implements IResourceExpungeService<JpaPid
|
|||
@Override
|
||||
@Transactional
|
||||
public void expungeHistoricalVersions(
|
||||
RequestDetails theRequestDetails, List<JpaPid> theHistoricalIds, AtomicInteger theRemainingCount) {
|
||||
for (JpaPid next : theHistoricalIds) {
|
||||
expungeHistoricalVersion(theRequestDetails, (next).getId(), theRemainingCount);
|
||||
RequestDetails theRequestDetails,
|
||||
List<ResourceHistoryTablePk> theHistoricalIds,
|
||||
AtomicInteger theRemainingCount) {
|
||||
for (ResourceHistoryTablePk next : theHistoricalIds) {
|
||||
expungeHistoricalVersion(theRequestDetails, next, theRemainingCount);
|
||||
if (expungeLimitReached(theRemainingCount)) {
|
||||
return;
|
||||
}
|
||||
|
@ -301,11 +296,12 @@ public class JpaResourceExpungeService implements IResourceExpungeService<JpaPid
|
|||
}
|
||||
|
||||
protected void expungeCurrentVersionOfResource(
|
||||
RequestDetails theRequestDetails, Long theResourceId, AtomicInteger theRemainingCount) {
|
||||
RequestDetails theRequestDetails, JpaPid theResourceId, AtomicInteger theRemainingCount) {
|
||||
|
||||
ResourceTable resource = myResourceTableDao.findById(theResourceId).orElseThrow(IllegalStateException::new);
|
||||
|
||||
ResourceHistoryTable currentVersion =
|
||||
myResourceHistoryTableDao.findForIdAndVersion(resource.getId(), resource.getVersion());
|
||||
myResourceHistoryTableDao.findForIdAndVersion(resource.getId().toFk(), resource.getVersion());
|
||||
if (currentVersion != null) {
|
||||
expungeHistoricalVersion(theRequestDetails, currentVersion.getId(), theRemainingCount);
|
||||
}
|
||||
|
@ -329,44 +325,43 @@ public class JpaResourceExpungeService implements IResourceExpungeService<JpaPid
|
|||
@Override
|
||||
@Transactional
|
||||
public void deleteAllSearchParams(JpaPid theResourceId) {
|
||||
Long theResourceLongId = theResourceId.getId();
|
||||
ResourceTable resource = myResourceTableDao.findById(theResourceLongId).orElse(null);
|
||||
ResourceTable resource = myResourceTableDao.findById(theResourceId).orElse(null);
|
||||
|
||||
if (resource == null || resource.isParamsUriPopulated()) {
|
||||
myResourceIndexedSearchParamUriDao.deleteByResourceId(theResourceLongId);
|
||||
myResourceIndexedSearchParamUriDao.deleteByResourceId(theResourceId);
|
||||
}
|
||||
if (resource == null || resource.isParamsCoordsPopulated()) {
|
||||
myResourceIndexedSearchParamCoordsDao.deleteByResourceId(theResourceLongId);
|
||||
myResourceIndexedSearchParamCoordsDao.deleteByResourceId(theResourceId);
|
||||
}
|
||||
if (resource == null || resource.isParamsDatePopulated()) {
|
||||
myResourceIndexedSearchParamDateDao.deleteByResourceId(theResourceLongId);
|
||||
myResourceIndexedSearchParamDateDao.deleteByResourceId(theResourceId);
|
||||
}
|
||||
if (resource == null || resource.isParamsNumberPopulated()) {
|
||||
myResourceIndexedSearchParamNumberDao.deleteByResourceId(theResourceLongId);
|
||||
myResourceIndexedSearchParamNumberDao.deleteByResourceId(theResourceId);
|
||||
}
|
||||
if (resource == null || resource.isParamsQuantityPopulated()) {
|
||||
myResourceIndexedSearchParamQuantityDao.deleteByResourceId(theResourceLongId);
|
||||
myResourceIndexedSearchParamQuantityDao.deleteByResourceId(theResourceId);
|
||||
}
|
||||
if (resource == null || resource.isParamsQuantityNormalizedPopulated()) {
|
||||
myResourceIndexedSearchParamQuantityNormalizedDao.deleteByResourceId(theResourceLongId);
|
||||
myResourceIndexedSearchParamQuantityNormalizedDao.deleteByResourceId(theResourceId);
|
||||
}
|
||||
if (resource == null || resource.isParamsStringPopulated()) {
|
||||
myResourceIndexedSearchParamStringDao.deleteByResourceId(theResourceLongId);
|
||||
myResourceIndexedSearchParamStringDao.deleteByResourceId(theResourceId);
|
||||
}
|
||||
if (resource == null || resource.isParamsTokenPopulated()) {
|
||||
myResourceIndexedSearchParamTokenDao.deleteByResourceId(theResourceLongId);
|
||||
myResourceIndexedSearchParamTokenDao.deleteByResourceId(theResourceId);
|
||||
}
|
||||
if (resource == null || resource.isParamsComboStringUniquePresent()) {
|
||||
myResourceIndexedCompositeStringUniqueDao.deleteByResourceId(theResourceLongId);
|
||||
myResourceIndexedCompositeStringUniqueDao.deleteByResourceId(theResourceId);
|
||||
}
|
||||
if (resource == null || resource.isParamsComboTokensNonUniquePresent()) {
|
||||
myResourceIndexedComboTokensNonUniqueDao.deleteByResourceId(theResourceLongId);
|
||||
myResourceIndexedComboTokensNonUniqueDao.deleteByResourceId(theResourceId);
|
||||
}
|
||||
if (myStorageSettings.getIndexMissingFields() == JpaStorageSettings.IndexEnabledEnum.ENABLED) {
|
||||
mySearchParamPresentDao.deleteByResourceId(theResourceLongId);
|
||||
mySearchParamPresentDao.deleteByResourceId(theResourceId);
|
||||
}
|
||||
if (resource == null || resource.isHasLinks()) {
|
||||
myResourceLinkDao.deleteByResourceId(theResourceLongId);
|
||||
myResourceLinkDao.deleteByResourceId(theResourceId);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -380,13 +375,13 @@ public class JpaResourceExpungeService implements IResourceExpungeService<JpaPid
|
|||
page = PageRequest.of(0, theRemainingCount.get());
|
||||
}
|
||||
|
||||
Slice<Long> versionIds =
|
||||
myResourceHistoryTableDao.findForResourceId(page, theResource.getId(), theResource.getVersion());
|
||||
Slice<ResourceHistoryTablePk> versionIds = myResourceHistoryTableDao.findForResourceId(
|
||||
page, theResource.getId().toFk(), theResource.getVersion());
|
||||
ourLog.debug(
|
||||
"Found {} versions of resource {} to expunge",
|
||||
versionIds.getNumberOfElements(),
|
||||
theResource.getIdDt().getValue());
|
||||
for (Long nextVersionId : versionIds) {
|
||||
for (ResourceHistoryTablePk nextVersionId : versionIds) {
|
||||
expungeHistoricalVersion(theRequestDetails, nextVersionId, theRemainingCount);
|
||||
if (expungeLimitReached(theRemainingCount)) {
|
||||
return;
|
||||
|
@ -394,9 +389,9 @@ public class JpaResourceExpungeService implements IResourceExpungeService<JpaPid
|
|||
}
|
||||
}
|
||||
|
||||
private Slice<Long> toSlice(ResourceHistoryTable myVersion) {
|
||||
Validate.notNull(myVersion);
|
||||
return new SliceImpl<>(Collections.singletonList(myVersion.getId()));
|
||||
private Slice<ResourceHistoryTablePk> toSlice(ResourceHistoryTable theVersion) {
|
||||
Validate.notNull(theVersion, "theVersion must not be null");
|
||||
return new SliceImpl<>(Collections.singletonList(theVersion.getId()));
|
||||
}
|
||||
|
||||
private boolean isEmptyQuery(int theCount) {
|
||||
|
|
|
@ -19,18 +19,21 @@
|
|||
*/
|
||||
package ca.uhn.fhir.jpa.dao.expunge;
|
||||
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
|
||||
public class ResourceForeignKey {
|
||||
public final String table;
|
||||
public final String key;
|
||||
public final String myTable;
|
||||
public final String myResourceIdColumn;
|
||||
public final String myPartitionIdColumn;
|
||||
|
||||
public ResourceForeignKey(String theTable, String theKey) {
|
||||
table = theTable;
|
||||
key = theKey;
|
||||
public ResourceForeignKey(String theTable, String thePartitionIdColumn, String theResourceIdColumn) {
|
||||
myTable = theTable;
|
||||
myPartitionIdColumn = thePartitionIdColumn;
|
||||
myResourceIdColumn = theResourceIdColumn;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -42,21 +45,56 @@ public class ResourceForeignKey {
|
|||
ResourceForeignKey that = (ResourceForeignKey) theO;
|
||||
|
||||
return new EqualsBuilder()
|
||||
.append(table, that.table)
|
||||
.append(key, that.key)
|
||||
.append(myTable, that.myTable)
|
||||
.append(myResourceIdColumn, that.myResourceIdColumn)
|
||||
.append(myPartitionIdColumn, that.myPartitionIdColumn)
|
||||
.isEquals();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return new HashCodeBuilder(17, 37).append(table).append(key).toHashCode();
|
||||
return new HashCodeBuilder(17, 37)
|
||||
.append(myTable)
|
||||
.append(myPartitionIdColumn)
|
||||
.append(myResourceIdColumn)
|
||||
.toHashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
|
||||
.append("table", table)
|
||||
.append("key", key)
|
||||
.append("table", myTable)
|
||||
.append("resourceIdColumn", myResourceIdColumn)
|
||||
.append("partitionIdColumn", myPartitionIdColumn)
|
||||
.toString();
|
||||
}
|
||||
|
||||
public static final class ResourceForeignKeyBuilder {
|
||||
private String myTable;
|
||||
private String myResourceIdColumn;
|
||||
private String myPartitionIdColumn;
|
||||
|
||||
public ResourceForeignKeyBuilder() {}
|
||||
|
||||
public void withTable(String myTable) {
|
||||
this.myTable = myTable;
|
||||
}
|
||||
|
||||
public void withResourceIdColumn(String myResourceIdColumn) {
|
||||
this.myResourceIdColumn = myResourceIdColumn;
|
||||
}
|
||||
|
||||
public void withPartitionIdColumn(String myPartitionIdColumn) {
|
||||
this.myPartitionIdColumn = myPartitionIdColumn;
|
||||
}
|
||||
|
||||
public ResourceForeignKey build() {
|
||||
Validate.notBlank(myTable, "Table is required");
|
||||
Validate.notBlank(myResourceIdColumn, "ResourceIdColumn is required");
|
||||
Validate.notBlank(
|
||||
myPartitionIdColumn,
|
||||
"PartitionIdColumn is required for table " + myTable + " and resource ID: " + myResourceIdColumn);
|
||||
return new ResourceForeignKey(this.myTable, this.myPartitionIdColumn, this.myResourceIdColumn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,16 @@ import org.springframework.stereotype.Service;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static ca.uhn.fhir.jpa.entity.MdmLink.GOLDEN_RESOURCE_PARTITION_ID;
|
||||
import static ca.uhn.fhir.jpa.entity.MdmLink.GOLDEN_RESOURCE_PID;
|
||||
import static ca.uhn.fhir.jpa.entity.MdmLink.PERSON_PARTITION_ID;
|
||||
import static ca.uhn.fhir.jpa.entity.MdmLink.PERSON_PID;
|
||||
import static ca.uhn.fhir.jpa.entity.MdmLink.TARGET_PARTITION_ID;
|
||||
import static ca.uhn.fhir.jpa.entity.MdmLink.TARGET_PID;
|
||||
import static ca.uhn.fhir.jpa.model.entity.PartitionablePartitionId.PARTITION_ID;
|
||||
import static ca.uhn.fhir.jpa.model.entity.ResourceLink.TARGET_RESOURCE_ID;
|
||||
import static ca.uhn.fhir.jpa.model.entity.ResourceLink.TARGET_RES_PARTITION_ID;
|
||||
|
||||
@Service
|
||||
public class ResourceTableFKProvider {
|
||||
@Autowired(required = false)
|
||||
|
@ -40,39 +50,38 @@ public class ResourceTableFKProvider {
|
|||
// SELECT FKTABLE_NAME, FKCOLUMN_NAME FROM CROSS_REFERENCES WHERE PKTABLE_NAME = 'HFJ_RESOURCE'
|
||||
|
||||
// Add some secondary related records that don't have foreign keys
|
||||
retval.add(new ResourceForeignKey("HFJ_HISTORY_TAG", "RES_ID")); // NOT covered by index.
|
||||
retval.add(new ResourceForeignKey("HFJ_RES_VER_PROV", "RES_PID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_HISTORY_TAG", PARTITION_ID, "RES_ID")); // NOT covered by index.
|
||||
retval.add(new ResourceForeignKey("HFJ_RES_VER_PROV", PARTITION_ID, "RES_PID"));
|
||||
|
||||
// These have the possibility of touching all resource types.
|
||||
retval.add(new ResourceForeignKey("HFJ_IDX_CMP_STRING_UNIQ", "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_IDX_CMB_TOK_NU", "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_RES_LINK", "SRC_RESOURCE_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_RES_LINK", "TARGET_RESOURCE_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_RES_PARAM_PRESENT", "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_RES_TAG", "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_RES_VER", "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_SPIDX_COORDS", "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_SPIDX_DATE", "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_SPIDX_NUMBER", "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_SPIDX_QUANTITY", "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_SPIDX_QUANTITY_NRML", "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_SPIDX_STRING", "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_SPIDX_TOKEN", "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_SPIDX_URI", "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("MPI_LINK", "GOLDEN_RESOURCE_PID"));
|
||||
retval.add(new ResourceForeignKey("MPI_LINK", "TARGET_PID"));
|
||||
retval.add(new ResourceForeignKey("MPI_LINK", "PERSON_PID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_IDX_CMP_STRING_UNIQ", PARTITION_ID, "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_IDX_CMB_TOK_NU", PARTITION_ID, "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_RES_LINK", PARTITION_ID, "SRC_RESOURCE_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_RES_LINK", TARGET_RES_PARTITION_ID, TARGET_RESOURCE_ID));
|
||||
retval.add(new ResourceForeignKey("HFJ_RES_PARAM_PRESENT", PARTITION_ID, "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_RES_TAG", PARTITION_ID, "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_RES_VER", PARTITION_ID, "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_SPIDX_COORDS", PARTITION_ID, "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_SPIDX_DATE", PARTITION_ID, "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_SPIDX_NUMBER", PARTITION_ID, "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_SPIDX_QUANTITY", PARTITION_ID, "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_SPIDX_QUANTITY_NRML", PARTITION_ID, "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_SPIDX_STRING", PARTITION_ID, "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_SPIDX_TOKEN", PARTITION_ID, "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_SPIDX_URI", PARTITION_ID, "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("MPI_LINK", GOLDEN_RESOURCE_PARTITION_ID, GOLDEN_RESOURCE_PID));
|
||||
retval.add(new ResourceForeignKey("MPI_LINK", TARGET_PARTITION_ID, TARGET_PID));
|
||||
retval.add(new ResourceForeignKey("MPI_LINK", PERSON_PARTITION_ID, PERSON_PID));
|
||||
|
||||
// These only touch certain resource types.
|
||||
retval.add(new ResourceForeignKey("TRM_CODESYSTEM_VER", "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("TRM_CODESYSTEM", "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("TRM_VALUESET", "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("TRM_CONCEPT_MAP", "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("NPM_PACKAGE_VER", "BINARY_RES_ID"));
|
||||
retval.add(new ResourceForeignKey("NPM_PACKAGE_VER_RES", "BINARY_RES_ID"));
|
||||
retval.add(new ResourceForeignKey("TRM_CODESYSTEM_VER", PARTITION_ID, "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("TRM_CODESYSTEM", PARTITION_ID, "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("TRM_VALUESET", PARTITION_ID, "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("TRM_CONCEPT_MAP", PARTITION_ID, "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("NPM_PACKAGE_VER", PARTITION_ID, "BINARY_RES_ID"));
|
||||
retval.add(new ResourceForeignKey("NPM_PACKAGE_VER_RES", PARTITION_ID, "BINARY_RES_ID"));
|
||||
|
||||
retval.add(new ResourceForeignKey("HFJ_SUBSCRIPTION_STATS", "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_RES_SEARCH_URL", "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_RES_SEARCH_URL", PARTITION_ID, "RES_ID"));
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
@ -81,50 +90,56 @@ public class ResourceTableFKProvider {
|
|||
public List<ResourceForeignKey> getResourceForeignKeysByResourceType(String theResourceType) {
|
||||
List<ResourceForeignKey> retval = new ArrayList<>();
|
||||
// These have the possibility of touching all resource types.
|
||||
retval.add(new ResourceForeignKey("HFJ_HISTORY_TAG", "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_RES_VER_PROV", "RES_PID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_IDX_CMP_STRING_UNIQ", "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_IDX_CMB_TOK_NU", "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_RES_LINK", "SRC_RESOURCE_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_RES_LINK", "TARGET_RESOURCE_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_RES_PARAM_PRESENT", "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_RES_TAG", "RES_ID")); // TODO GGG: Res_ID + TAG_ID? is that enough?
|
||||
retval.add(new ResourceForeignKey("HFJ_RES_VER", "RES_ID")); // TODO GGG: RES_ID + updated? is that enough?
|
||||
retval.add(new ResourceForeignKey("HFJ_SPIDX_COORDS", "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_SPIDX_DATE", "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_SPIDX_NUMBER", "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_SPIDX_QUANTITY", "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_SPIDX_QUANTITY_NRML", "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_SPIDX_STRING", "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_SPIDX_TOKEN", "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_SPIDX_URI", "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_HISTORY_TAG", PARTITION_ID, "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_RES_VER_PROV", PARTITION_ID, "RES_PID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_IDX_CMP_STRING_UNIQ", PARTITION_ID, "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_IDX_CMB_TOK_NU", PARTITION_ID, "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_RES_LINK", PARTITION_ID, "SRC_RESOURCE_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_RES_LINK", TARGET_PARTITION_ID, TARGET_RESOURCE_ID));
|
||||
retval.add(new ResourceForeignKey("HFJ_RES_PARAM_PRESENT", PARTITION_ID, "RES_ID"));
|
||||
retval.add(new ResourceForeignKey(
|
||||
"HFJ_RES_TAG", PARTITION_ID, "RES_ID")); // TODO GGG: Res_ID + TAG_ID? is that enough?
|
||||
retval.add(new ResourceForeignKey(
|
||||
"HFJ_RES_VER", PARTITION_ID, "RES_ID")); // TODO GGG: RES_ID + updated? is that enough?
|
||||
retval.add(new ResourceForeignKey("HFJ_SPIDX_COORDS", PARTITION_ID, "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_SPIDX_DATE", PARTITION_ID, "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_SPIDX_NUMBER", PARTITION_ID, "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_SPIDX_QUANTITY", PARTITION_ID, "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_SPIDX_QUANTITY_NRML", PARTITION_ID, "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_SPIDX_STRING", PARTITION_ID, "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_SPIDX_TOKEN", PARTITION_ID, "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_SPIDX_URI", PARTITION_ID, "RES_ID"));
|
||||
|
||||
if (myMdmSettings != null && myMdmSettings.isEnabled()) {
|
||||
retval.add(new ResourceForeignKey("MPI_LINK", "GOLDEN_RESOURCE_PID")); // NOT covered by index.
|
||||
retval.add(new ResourceForeignKey("MPI_LINK", "TARGET_PID")); // Possibly covered, partial index
|
||||
retval.add(new ResourceForeignKey(
|
||||
"MPI_LINK", GOLDEN_RESOURCE_PARTITION_ID, GOLDEN_RESOURCE_PID)); // NOT covered by index.
|
||||
retval.add(new ResourceForeignKey(
|
||||
"MPI_LINK", TARGET_PARTITION_ID, TARGET_PID)); // Possibly covered, partial index
|
||||
retval.add(new ResourceForeignKey(
|
||||
"MPI_LINK",
|
||||
"PERSON_PID")); // TODO GGG: I don't even think we need this... this field is deprecated, and the
|
||||
PERSON_PARTITION_ID,
|
||||
PERSON_PID)); // TODO GGG: I don't even think we need this... this field is deprecated, and the
|
||||
// deletion is covered by GOLDEN_RESOURCE_PID
|
||||
}
|
||||
|
||||
switch (theResourceType.toLowerCase()) {
|
||||
case "binary":
|
||||
retval.add(new ResourceForeignKey("NPM_PACKAGE_VER", "BINARY_RES_ID")); // Not covered
|
||||
retval.add(new ResourceForeignKey("NPM_PACKAGE_VER_RES", "BINARY_RES_ID")); // Not covered
|
||||
retval.add(new ResourceForeignKey("NPM_PACKAGE_VER", PARTITION_ID, "BINARY_RES_ID")); // Not covered
|
||||
retval.add(new ResourceForeignKey("NPM_PACKAGE_VER_RES", PARTITION_ID, "BINARY_RES_ID")); // Not covered
|
||||
break;
|
||||
case "subscription":
|
||||
retval.add(new ResourceForeignKey("HFJ_SUBSCRIPTION_STATS", "RES_ID")); // Covered by index.
|
||||
retval.add(
|
||||
new ResourceForeignKey("HFJ_SUBSCRIPTION_STATS", PARTITION_ID, "RES_ID")); // Covered by index.
|
||||
break;
|
||||
case "codesystem":
|
||||
retval.add(new ResourceForeignKey("TRM_CODESYSTEM_VER", "RES_ID")); // Not covered
|
||||
retval.add(new ResourceForeignKey("TRM_CODESYSTEM", "RES_ID")); // Not covered
|
||||
retval.add(new ResourceForeignKey("TRM_CODESYSTEM_VER", PARTITION_ID, "RES_ID")); // Not covered
|
||||
retval.add(new ResourceForeignKey("TRM_CODESYSTEM", PARTITION_ID, "RES_ID")); // Not covered
|
||||
break;
|
||||
case "valueset":
|
||||
retval.add(new ResourceForeignKey("TRM_VALUESET", "RES_ID")); // Not covered
|
||||
retval.add(new ResourceForeignKey("TRM_VALUESET", PARTITION_ID, "RES_ID")); // Not covered
|
||||
break;
|
||||
case "conceptmap":
|
||||
retval.add(new ResourceForeignKey("TRM_CONCEPT_MAP", "RES_ID")); // Not covered
|
||||
retval.add(new ResourceForeignKey("TRM_CONCEPT_MAP", PARTITION_ID, "RES_ID")); // Not covered
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
|
|
@ -115,6 +115,7 @@ public class DaoSearchParamSynchronizer {
|
|||
@Nullable IPreSaveHook<T> theAddParamPreSaveHook) {
|
||||
Collection<T> newParams = theNewParams;
|
||||
for (T next : newParams) {
|
||||
next.setResourceId(theEntity.getId().getId());
|
||||
next.setPartitionId(theEntity.getPartitionId());
|
||||
next.calculateHashes();
|
||||
}
|
||||
|
@ -169,12 +170,24 @@ public class DaoSearchParamSynchronizer {
|
|||
}
|
||||
|
||||
for (T next : paramsToAdd) {
|
||||
myEntityManager.merge(next);
|
||||
if (next.getId() == null) {
|
||||
myEntityManager.persist(next);
|
||||
} else {
|
||||
myEntityManager.merge(next);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: are there any unintended consequences to fixing this bug?
|
||||
theAddRemoveCount.addToAddCount(paramsToAdd.size());
|
||||
theAddRemoveCount.addToRemoveCount(paramsToRemove.size());
|
||||
|
||||
// Replace the existing "new set" with the set of params we should be adding.
|
||||
// We're going to add them back into the entity just in case it gets updated
|
||||
// a second time within the same transaction
|
||||
theNewParams.clear();
|
||||
theNewParams.addAll(theExistingParams);
|
||||
theNewParams.addAll(paramsToAdd);
|
||||
theNewParams.removeAll(paramsToRemove);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -331,7 +331,7 @@ public class IdHelperService implements IIdHelperService<JpaPid> {
|
|||
CriteriaQuery<Tuple> criteriaQuery = cb.createTupleQuery();
|
||||
Root<ResourceTable> from = criteriaQuery.from(ResourceTable.class);
|
||||
criteriaQuery.multiselect(
|
||||
from.get("myId"),
|
||||
from.get("myPid"),
|
||||
from.get("myResourceType"),
|
||||
from.get("myFhirId"),
|
||||
from.get("myDeleted"),
|
||||
|
@ -363,12 +363,15 @@ public class IdHelperService implements IIdHelperService<JpaPid> {
|
|||
List<Tuple> results = query.getResultList();
|
||||
for (Tuple nextId : results) {
|
||||
// Check if the nextId has a resource ID. It may have a null resource ID if a commit is still pending.
|
||||
Long resourcePid = nextId.get(0, Long.class);
|
||||
JpaPid resourcePid = nextId.get(0, JpaPid.class);
|
||||
String resourceType = nextId.get(1, String.class);
|
||||
String fhirId = nextId.get(2, String.class);
|
||||
Date deletedAd = nextId.get(3, Date.class);
|
||||
Integer partitionId = nextId.get(4, Integer.class);
|
||||
if (resourcePid != null) {
|
||||
if (resourcePid.getPartitionId() == null && partitionId != null) {
|
||||
resourcePid.setPartitionId(partitionId);
|
||||
}
|
||||
JpaResourceLookup lookup = new JpaResourceLookup(
|
||||
resourceType, fhirId, resourcePid, deletedAd, PartitionablePartitionId.with(partitionId, null));
|
||||
|
||||
|
@ -458,7 +461,7 @@ public class IdHelperService implements IIdHelperService<JpaPid> {
|
|||
if (forcedId.isPresent()) {
|
||||
retVal.setValue(forcedId.get());
|
||||
} else {
|
||||
retVal.setValue(theResourceType + '/' + theId);
|
||||
retVal.setValue(theResourceType + '/' + theId.getId());
|
||||
}
|
||||
|
||||
return retVal;
|
||||
|
@ -469,14 +472,14 @@ public class IdHelperService implements IIdHelperService<JpaPid> {
|
|||
public Optional<String> translatePidIdToForcedIdWithCache(JpaPid theId) {
|
||||
// do getIfPresent and then put to avoid doing I/O inside the cache.
|
||||
Optional<String> forcedId =
|
||||
myMemoryCacheService.getIfPresent(MemoryCacheService.CacheEnum.PID_TO_FORCED_ID, theId.getId());
|
||||
myMemoryCacheService.getIfPresent(MemoryCacheService.CacheEnum.PID_TO_FORCED_ID, theId);
|
||||
|
||||
if (forcedId == null) {
|
||||
// This is only called when we know the resource exists.
|
||||
// So this optional is only empty when there is no hfj_forced_id table
|
||||
// note: this is obsolete with the new fhir_id column, and will go away.
|
||||
forcedId = myResourceTableDao.findById(theId.getId()).map(ResourceTable::asTypedFhirResourceId);
|
||||
myMemoryCacheService.put(MemoryCacheService.CacheEnum.PID_TO_FORCED_ID, theId.getId(), forcedId);
|
||||
forcedId = myResourceTableDao.findById(theId).map(ResourceTable::asTypedFhirResourceId);
|
||||
myMemoryCacheService.put(MemoryCacheService.CacheEnum.PID_TO_FORCED_ID, theId, forcedId);
|
||||
}
|
||||
|
||||
return forcedId;
|
||||
|
@ -497,18 +500,17 @@ public class IdHelperService implements IIdHelperService<JpaPid> {
|
|||
@Override
|
||||
public PersistentIdToForcedIdMap<JpaPid> translatePidsToForcedIds(Set<JpaPid> theResourceIds) {
|
||||
assert myDontCheckActiveTransactionForUnitTest || TransactionSynchronizationManager.isSynchronizationActive();
|
||||
Set<Long> thePids = theResourceIds.stream().map(JpaPid::getId).collect(Collectors.toSet());
|
||||
Map<Long, Optional<String>> retVal = new HashMap<>(
|
||||
myMemoryCacheService.getAllPresent(MemoryCacheService.CacheEnum.PID_TO_FORCED_ID, thePids));
|
||||
HashMap<JpaPid, Optional<String>> retVal = new HashMap<>(
|
||||
myMemoryCacheService.getAllPresent(MemoryCacheService.CacheEnum.PID_TO_FORCED_ID, theResourceIds));
|
||||
|
||||
List<Long> remainingPids =
|
||||
thePids.stream().filter(t -> !retVal.containsKey(t)).collect(Collectors.toList());
|
||||
List<JpaPid> remainingPids =
|
||||
theResourceIds.stream().filter(t -> !retVal.containsKey(t)).collect(Collectors.toList());
|
||||
|
||||
QueryChunker.chunk(remainingPids, t -> {
|
||||
new QueryChunker<JpaPid>().chunk(remainingPids, t -> {
|
||||
List<ResourceTable> resourceEntities = myResourceTableDao.findAllById(t);
|
||||
|
||||
for (ResourceTable nextResourceEntity : resourceEntities) {
|
||||
Long nextResourcePid = nextResourceEntity.getId();
|
||||
JpaPid nextResourcePid = nextResourceEntity.getPersistentId();
|
||||
Optional<String> nextForcedId = Optional.of(nextResourceEntity.asTypedFhirResourceId());
|
||||
retVal.put(nextResourcePid, nextForcedId);
|
||||
myMemoryCacheService.putAfterCommit(
|
||||
|
@ -516,14 +518,14 @@ public class IdHelperService implements IIdHelperService<JpaPid> {
|
|||
}
|
||||
});
|
||||
|
||||
remainingPids = thePids.stream().filter(t -> !retVal.containsKey(t)).collect(Collectors.toList());
|
||||
for (Long nextResourcePid : remainingPids) {
|
||||
remainingPids =
|
||||
theResourceIds.stream().filter(t -> !retVal.containsKey(t)).collect(Collectors.toList());
|
||||
for (JpaPid nextResourcePid : remainingPids) {
|
||||
retVal.put(nextResourcePid, Optional.empty());
|
||||
myMemoryCacheService.putAfterCommit(
|
||||
MemoryCacheService.CacheEnum.PID_TO_FORCED_ID, nextResourcePid, Optional.empty());
|
||||
}
|
||||
Map<JpaPid, Optional<String>> convertRetVal = new HashMap<>();
|
||||
retVal.forEach((k, v) -> convertRetVal.put(JpaPid.fromId(k), v));
|
||||
Map<JpaPid, Optional<String>> convertRetVal = new HashMap<>(retVal);
|
||||
|
||||
return new PersistentIdToForcedIdMap<>(convertRetVal);
|
||||
}
|
||||
|
@ -548,7 +550,7 @@ public class IdHelperService implements IIdHelperService<JpaPid> {
|
|||
|
||||
myMemoryCacheService.putAfterCommit(
|
||||
MemoryCacheService.CacheEnum.PID_TO_FORCED_ID,
|
||||
theJpaPid.getId(),
|
||||
theJpaPid,
|
||||
Optional.of(theResourceType + "/" + theFhirId));
|
||||
|
||||
JpaResourceLookup lookup = new JpaResourceLookup(
|
||||
|
@ -592,7 +594,7 @@ public class IdHelperService implements IIdHelperService<JpaPid> {
|
|||
retVal = null;
|
||||
}
|
||||
} else {
|
||||
retVal = JpaPid.fromId(Long.parseLong(resourceId.toString()));
|
||||
retVal = (JpaPid) resourceId;
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
@ -600,19 +602,19 @@ public class IdHelperService implements IIdHelperService<JpaPid> {
|
|||
@Override
|
||||
@Nonnull
|
||||
public JpaPid getPidOrThrowException(@Nonnull IAnyResource theResource) {
|
||||
Long theResourcePID = (Long) theResource.getUserData(RESOURCE_PID);
|
||||
JpaPid theResourcePID = (JpaPid) theResource.getUserData(RESOURCE_PID);
|
||||
if (theResourcePID == null) {
|
||||
throw new IllegalStateException(Msg.code(2108)
|
||||
+ String.format(
|
||||
"Unable to find %s in the user data for %s with ID %s",
|
||||
RESOURCE_PID, theResource, theResource.getId()));
|
||||
}
|
||||
return JpaPid.fromId(theResourcePID);
|
||||
return theResourcePID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IIdType resourceIdFromPidOrThrowException(JpaPid thePid, String theResourceType) {
|
||||
Optional<ResourceTable> optionalResource = myResourceTableDao.findById(thePid.getId());
|
||||
Optional<ResourceTable> optionalResource = myResourceTableDao.findById(thePid);
|
||||
if (optionalResource.isEmpty()) {
|
||||
throw new ResourceNotFoundException(Msg.code(2124) + "Requested resource not found");
|
||||
}
|
||||
|
@ -645,8 +647,15 @@ public class IdHelperService implements IIdHelperService<JpaPid> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public JpaPid newPidFromStringIdAndResourceName(String thePid, String theResourceName) {
|
||||
return JpaPid.fromIdAndResourceType(Long.parseLong(thePid), theResourceName);
|
||||
public JpaPid newPid(Object thePid, Integer thePartitionId) {
|
||||
return JpaPid.fromId((Long) thePid, thePartitionId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JpaPid newPidFromStringIdAndResourceName(Integer thePartitionId, String thePid, String theResourceName) {
|
||||
JpaPid retVal = JpaPid.fromId(Long.parseLong(thePid), thePartitionId);
|
||||
retVal.setResourceType(theResourceName);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private IIdType newIdType(String theValue) {
|
||||
|
|
|
@ -40,32 +40,18 @@ public class FhirResourceDaoSubscriptionR4 extends BaseHapiFhirResourceDao<Subsc
|
|||
@Autowired
|
||||
private ISubscriptionTableDao mySubscriptionTableDao;
|
||||
|
||||
private void createSubscriptionTable(ResourceTable theEntity, Subscription theSubscription) {
|
||||
SubscriptionTable subscriptionEntity = new SubscriptionTable();
|
||||
subscriptionEntity.setCreated(new Date());
|
||||
subscriptionEntity.setSubscriptionResource(theEntity);
|
||||
myEntityManager.persist(subscriptionEntity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getSubscriptionTablePidForSubscriptionResource(
|
||||
IIdType theId, RequestDetails theRequest, TransactionDetails theTransactionDetails) {
|
||||
ResourceTable entity = readEntityLatestVersion(theId, theRequest, theTransactionDetails);
|
||||
SubscriptionTable table = mySubscriptionTableDao.findOneByResourcePid(entity.getId());
|
||||
SubscriptionTable table =
|
||||
mySubscriptionTableDao.findOneByResourcePid(entity.getId().getId());
|
||||
if (table == null) {
|
||||
return null;
|
||||
}
|
||||
return table.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void postPersist(
|
||||
ResourceTable theEntity, Subscription theSubscription, RequestDetails theRequestDetails) {
|
||||
super.postPersist(theEntity, theSubscription, theRequestDetails);
|
||||
|
||||
createSubscriptionTable(theEntity, theSubscription);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceTable updateEntity(
|
||||
RequestDetails theRequest,
|
||||
|
@ -92,7 +78,8 @@ public class FhirResourceDaoSubscriptionR4 extends BaseHapiFhirResourceDao<Subsc
|
|||
Long subscriptionId = getSubscriptionTablePidForSubscriptionResource(
|
||||
theEntity.getIdDt(), theRequest, theTransactionDetails);
|
||||
if (subscriptionId != null) {
|
||||
mySubscriptionTableDao.deleteAllForSubscription(retVal);
|
||||
mySubscriptionTableDao.deleteAllForSubscription(
|
||||
retVal.getResourceId().getId());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -40,32 +40,18 @@ public class FhirResourceDaoSubscriptionR5 extends BaseHapiFhirResourceDao<Subsc
|
|||
@Autowired
|
||||
private ISubscriptionTableDao mySubscriptionTableDao;
|
||||
|
||||
private void createSubscriptionTable(ResourceTable theEntity, Subscription theSubscription) {
|
||||
SubscriptionTable subscriptionEntity = new SubscriptionTable();
|
||||
subscriptionEntity.setCreated(new Date());
|
||||
subscriptionEntity.setSubscriptionResource(theEntity);
|
||||
myEntityManager.persist(subscriptionEntity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getSubscriptionTablePidForSubscriptionResource(
|
||||
IIdType theId, RequestDetails theRequest, TransactionDetails theTransactionDetails) {
|
||||
ResourceTable entity = readEntityLatestVersion(theId, theRequest, theTransactionDetails);
|
||||
SubscriptionTable table = mySubscriptionTableDao.findOneByResourcePid(entity.getId());
|
||||
SubscriptionTable table =
|
||||
mySubscriptionTableDao.findOneByResourcePid(entity.getId().getId());
|
||||
if (table == null) {
|
||||
return null;
|
||||
}
|
||||
return table.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void postPersist(
|
||||
ResourceTable theEntity, Subscription theSubscription, RequestDetails theRequestDetails) {
|
||||
super.postPersist(theEntity, theSubscription, theRequestDetails);
|
||||
|
||||
createSubscriptionTable(theEntity, theSubscription);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceTable updateEntity(
|
||||
RequestDetails theRequest,
|
||||
|
@ -92,7 +78,8 @@ public class FhirResourceDaoSubscriptionR5 extends BaseHapiFhirResourceDao<Subsc
|
|||
Long subscriptionId = getSubscriptionTablePidForSubscriptionResource(
|
||||
theEntity.getIdDt(), theRequest, theTransactionDetails);
|
||||
if (subscriptionId != null) {
|
||||
mySubscriptionTableDao.deleteAllForSubscription(retVal);
|
||||
mySubscriptionTableDao.deleteAllForSubscription(
|
||||
retVal.getResourceId().getId());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
package ca.uhn.fhir.jpa.dao.search;
|
||||
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.jpa.model.dao.JpaPid;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.parser.IParser;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
@ -31,11 +32,11 @@ import org.hl7.fhir.instance.model.api.IBaseResource;
|
|||
public class ExtendedHSearchResourceProjection {
|
||||
public static final String RESOURCE_NOT_STORED_ERROR = "Resource not stored in search index: ";
|
||||
|
||||
final long myPid;
|
||||
final JpaPid myPid;
|
||||
final String myForcedId;
|
||||
final String myResourceString;
|
||||
|
||||
public ExtendedHSearchResourceProjection(long thePid, String theForcedId, String theResourceString) {
|
||||
public ExtendedHSearchResourceProjection(JpaPid thePid, String theForcedId, String theResourceString) {
|
||||
if (StringUtils.isEmpty(theResourceString)) {
|
||||
throw new ResourceNotFoundInIndexException(Msg.code(2130) + RESOURCE_NOT_STORED_ERROR + thePid);
|
||||
}
|
||||
|
@ -51,7 +52,7 @@ public class ExtendedHSearchResourceProjection {
|
|||
if (myForcedId != null) {
|
||||
id = new IdDt(myForcedId);
|
||||
} else {
|
||||
id = new IdDt(myPid);
|
||||
id = new IdDt(myPid.getId());
|
||||
}
|
||||
result.setId(id);
|
||||
|
||||
|
@ -59,6 +60,6 @@ public class ExtendedHSearchResourceProjection {
|
|||
}
|
||||
|
||||
public long getPid() {
|
||||
return myPid;
|
||||
return myPid.getId();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,10 +30,10 @@ import java.util.Iterator;
|
|||
* Adapt Hibernate Search SearchScroll paging result to our ISearchQueryExecutor
|
||||
*/
|
||||
public class SearchScrollQueryExecutorAdaptor implements ISearchQueryExecutor {
|
||||
private final SearchScroll<Long> myScroll;
|
||||
private Iterator<Long> myCurrentIterator;
|
||||
private final SearchScroll<JpaPid> myScroll;
|
||||
private Iterator<JpaPid> myCurrentIterator;
|
||||
|
||||
public SearchScrollQueryExecutorAdaptor(SearchScroll<Long> theScroll) {
|
||||
public SearchScrollQueryExecutorAdaptor(SearchScroll<JpaPid> theScroll) {
|
||||
myScroll = theScroll;
|
||||
advanceNextScrollPage();
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ public class SearchScrollQueryExecutorAdaptor implements ISearchQueryExecutor {
|
|||
* Note: the last page will have 0 hits.
|
||||
*/
|
||||
private void advanceNextScrollPage() {
|
||||
SearchScrollResult<Long> scrollResults = myScroll.next();
|
||||
SearchScrollResult<JpaPid> scrollResults = myScroll.next();
|
||||
myCurrentIterator = scrollResults.hits().iterator();
|
||||
}
|
||||
|
||||
|
@ -59,11 +59,11 @@ public class SearchScrollQueryExecutorAdaptor implements ISearchQueryExecutor {
|
|||
|
||||
@Override
|
||||
public JpaPid next() {
|
||||
Long result = myCurrentIterator.next();
|
||||
JpaPid result = myCurrentIterator.next();
|
||||
// was this the last in the current scroll page?
|
||||
if (!myCurrentIterator.hasNext()) {
|
||||
advanceNextScrollPage();
|
||||
}
|
||||
return JpaPid.fromId(result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ public class DeleteConflictFinderService {
|
|||
|
||||
List<ResourceLink> findConflicts(ResourceTable theEntity, int maxResults) {
|
||||
TypedQuery<ResourceLink> query = myEntityManager.createQuery(
|
||||
"SELECT l FROM ResourceLink l WHERE l.myTargetResourcePid = :target_pid", ResourceLink.class);
|
||||
"SELECT l FROM ResourceLink l WHERE l.myTargetResource.myPid = :target_pid", ResourceLink.class);
|
||||
query.setParameter("target_pid", theEntity.getId());
|
||||
query.setMaxResults(maxResults);
|
||||
return query.getResultList();
|
||||
|
|
|
@ -25,6 +25,7 @@ import ca.uhn.fhir.jpa.api.svc.IIdHelperService;
|
|||
import ca.uhn.fhir.jpa.dao.data.IResourceLinkDao;
|
||||
import ca.uhn.fhir.jpa.dao.expunge.ResourceForeignKey;
|
||||
import ca.uhn.fhir.jpa.dao.expunge.ResourceTableFKProvider;
|
||||
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
||||
import ca.uhn.fhir.jpa.model.dao.JpaPid;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceLink;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
|
@ -34,57 +35,63 @@ import org.slf4j.LoggerFactory;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static ca.uhn.fhir.jpa.model.entity.PartitionablePartitionId.PARTITION_ID;
|
||||
|
||||
public class DeleteExpungeSqlBuilder {
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(DeleteExpungeSqlBuilder.class);
|
||||
private final ResourceTableFKProvider myResourceTableFKProvider;
|
||||
private final JpaStorageSettings myStorageSettings;
|
||||
private final IIdHelperService myIdHelper;
|
||||
private final PartitionSettings myPartitionSettings;
|
||||
private final IIdHelperService<JpaPid> myIdHelper;
|
||||
private final IResourceLinkDao myResourceLinkDao;
|
||||
|
||||
public DeleteExpungeSqlBuilder(
|
||||
ResourceTableFKProvider theResourceTableFKProvider,
|
||||
JpaStorageSettings theStorageSettings,
|
||||
IIdHelperService theIdHelper,
|
||||
IResourceLinkDao theResourceLinkDao) {
|
||||
IIdHelperService<JpaPid> theIdHelper,
|
||||
IResourceLinkDao theResourceLinkDao,
|
||||
PartitionSettings thePartitionSettings) {
|
||||
myResourceTableFKProvider = theResourceTableFKProvider;
|
||||
myStorageSettings = theStorageSettings;
|
||||
myIdHelper = theIdHelper;
|
||||
myResourceLinkDao = theResourceLinkDao;
|
||||
myPartitionSettings = thePartitionSettings;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
DeleteExpungeSqlResult convertPidsToDeleteExpungeSql(
|
||||
List<JpaPid> theJpaPids, boolean theCascade, Integer theCascadeMaxRounds) {
|
||||
|
||||
Set<Long> pids = JpaPid.toLongSet(theJpaPids);
|
||||
Set<JpaPid> pids = new HashSet<>(theJpaPids);
|
||||
validateOkToDeleteAndExpunge(pids, theCascade, theCascadeMaxRounds);
|
||||
|
||||
List<String> rawSql = new ArrayList<>();
|
||||
|
||||
String pidListString = pids.toString().replace("[", "(").replace("]", ")");
|
||||
List<ResourceForeignKey> resourceForeignKeys = myResourceTableFKProvider.getResourceForeignKeys();
|
||||
|
||||
for (ResourceForeignKey resourceForeignKey : resourceForeignKeys) {
|
||||
rawSql.add(deleteRecordsByColumnSql(pidListString, resourceForeignKey));
|
||||
rawSql.add(deleteRecordsByColumnSql(pids, resourceForeignKey));
|
||||
}
|
||||
|
||||
// Lastly we need to delete records from the resource table all of these other tables link to:
|
||||
ResourceForeignKey resourceTablePk = new ResourceForeignKey("HFJ_RESOURCE", "RES_ID");
|
||||
rawSql.add(deleteRecordsByColumnSql(pidListString, resourceTablePk));
|
||||
ResourceForeignKey resourceTablePk = new ResourceForeignKey("HFJ_RESOURCE", PARTITION_ID, "RES_ID");
|
||||
rawSql.add(deleteRecordsByColumnSql(pids, resourceTablePk));
|
||||
return new DeleteExpungeSqlResult(rawSql, pids.size());
|
||||
}
|
||||
|
||||
public void validateOkToDeleteAndExpunge(Set<Long> thePids, boolean theCascade, Integer theCascadeMaxRounds) {
|
||||
public void validateOkToDeleteAndExpunge(Set<JpaPid> thePids, boolean theCascade, Integer theCascadeMaxRounds) {
|
||||
if (!myStorageSettings.isEnforceReferentialIntegrityOnDelete()) {
|
||||
ourLog.info("Referential integrity on delete disabled. Skipping referential integrity check.");
|
||||
return;
|
||||
}
|
||||
|
||||
List<JpaPid> targetPidsAsResourceIds = JpaPid.fromLongList(thePids);
|
||||
List<JpaPid> targetPidsAsResourceIds = List.copyOf(thePids);
|
||||
List<ResourceLink> conflictResourceLinks = Collections.synchronizedList(new ArrayList<>());
|
||||
findResourceLinksWithTargetPidIn(targetPidsAsResourceIds, targetPidsAsResourceIds, conflictResourceLinks);
|
||||
|
||||
|
@ -106,9 +113,9 @@ public class DeleteExpungeSqlBuilder {
|
|||
while (true) {
|
||||
List<JpaPid> addedThisRound = new ArrayList<>();
|
||||
for (ResourceLink next : conflictResourceLinks) {
|
||||
Long nextPid = next.getSourceResourcePid();
|
||||
JpaPid nextPid = next.getSourceResourcePk();
|
||||
if (thePids.add(nextPid)) {
|
||||
addedThisRound.add(JpaPid.fromId(nextPid));
|
||||
addedThisRound.add(nextPid);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -131,11 +138,11 @@ public class DeleteExpungeSqlBuilder {
|
|||
// NB-GGG: We previously instantiated these ID values from firstConflict.getSourceResource().getIdDt(), but in a
|
||||
// situation where we
|
||||
// actually had to run delete conflict checks in multiple partitions, the executor service starts its own
|
||||
// sessions on a per thread basis, and by the time
|
||||
// sessions on a per-thread basis, and by the time
|
||||
// we arrive here, those sessions are closed. So instead, we resolve them from PIDs, which are eagerly loaded.
|
||||
String sourceResourceId = myIdHelper
|
||||
.resourceIdFromPidOrThrowException(
|
||||
JpaPid.fromId(firstConflict.getSourceResourcePid()), firstConflict.getSourceResourceType())
|
||||
firstConflict.getSourceResourcePk(), firstConflict.getSourceResourceType())
|
||||
.toVersionless()
|
||||
.getValue();
|
||||
String targetResourceId = myIdHelper
|
||||
|
@ -153,19 +160,17 @@ public class DeleteExpungeSqlBuilder {
|
|||
List<JpaPid> theAllTargetPids,
|
||||
List<JpaPid> theSomeTargetPids,
|
||||
List<ResourceLink> theConflictResourceLinks) {
|
||||
List<Long> allTargetPidsAsLongs = JpaPid.toLongList(theAllTargetPids);
|
||||
List<Long> someTargetPidsAsLongs = JpaPid.toLongList(theSomeTargetPids);
|
||||
// We only need to find one conflict, so if we found one already in an earlier partition run, we can skip the
|
||||
// rest of the searches
|
||||
if (theConflictResourceLinks.isEmpty()) {
|
||||
List<ResourceLink> conflictResourceLinks =
|
||||
myResourceLinkDao.findWithTargetPidIn(someTargetPidsAsLongs).stream()
|
||||
myResourceLinkDao.findWithTargetPidIn((theSomeTargetPids)).stream()
|
||||
// Filter out resource links for which we are planning to delete the source.
|
||||
// theAllTargetPids contains a list of all the pids we are planning to delete. So we only
|
||||
// want
|
||||
// to consider a link to be a conflict if the source of that link is not in
|
||||
// theAllTargetPids.
|
||||
.filter(link -> !allTargetPidsAsLongs.contains(link.getSourceResourcePid()))
|
||||
.filter(link -> !(theAllTargetPids).contains(link.getSourceResourcePk()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// We do this in two steps to avoid lock contention on this synchronized list
|
||||
|
@ -173,9 +178,39 @@ public class DeleteExpungeSqlBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
private String deleteRecordsByColumnSql(String thePidListString, ResourceForeignKey theResourceForeignKey) {
|
||||
return "DELETE FROM " + theResourceForeignKey.table + " WHERE " + theResourceForeignKey.key + " IN "
|
||||
+ thePidListString;
|
||||
private String deleteRecordsByColumnSql(Set<JpaPid> thePids, ResourceForeignKey theResourceForeignKey) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("DELETE FROM ");
|
||||
builder.append(theResourceForeignKey.myTable);
|
||||
builder.append(" WHERE ");
|
||||
if (myPartitionSettings.isPartitionIdsInPrimaryKeys()) {
|
||||
builder.append("(");
|
||||
builder.append(theResourceForeignKey.myPartitionIdColumn);
|
||||
builder.append(",");
|
||||
builder.append(theResourceForeignKey.myResourceIdColumn);
|
||||
builder.append(")");
|
||||
} else {
|
||||
builder.append(theResourceForeignKey.myResourceIdColumn);
|
||||
}
|
||||
|
||||
builder.append(" IN (");
|
||||
for (Iterator<JpaPid> iter = thePids.iterator(); iter.hasNext(); ) {
|
||||
JpaPid pid = iter.next();
|
||||
if (myPartitionSettings.isPartitionIdsInPrimaryKeys()) {
|
||||
builder.append("(");
|
||||
builder.append(pid.getPartitionId());
|
||||
builder.append(",");
|
||||
builder.append(pid.getId());
|
||||
builder.append(")");
|
||||
} else {
|
||||
builder.append(pid.getId());
|
||||
}
|
||||
if (iter.hasNext()) {
|
||||
builder.append(",");
|
||||
}
|
||||
}
|
||||
builder.append(")");
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
public static class DeleteExpungeSqlResult {
|
||||
|
@ -183,8 +218,8 @@ public class DeleteExpungeSqlBuilder {
|
|||
private final List<String> mySqlStatements;
|
||||
private final int myRecordCount;
|
||||
|
||||
public DeleteExpungeSqlResult(List<String> theSqlStatments, int theRecordCount) {
|
||||
mySqlStatements = theSqlStatments;
|
||||
public DeleteExpungeSqlResult(List<String> theSqlStatements, int theRecordCount) {
|
||||
mySqlStatements = theSqlStatements;
|
||||
myRecordCount = theRecordCount;
|
||||
}
|
||||
|
||||
|
|
|
@ -28,8 +28,8 @@ import org.slf4j.Logger;
|
|||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class DeleteExpungeSvcImpl implements IDeleteExpungeSvc<JpaPid> {
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(DeleteExpungeSvcImpl.class);
|
||||
|
@ -78,8 +78,7 @@ public class DeleteExpungeSvcImpl implements IDeleteExpungeSvc<JpaPid> {
|
|||
*/
|
||||
private void clearHibernateSearchIndex(List<JpaPid> thePersistentIds) {
|
||||
if (myFullTextSearchSvc != null && !myFullTextSearchSvc.isDisabled()) {
|
||||
List<Object> objectIds =
|
||||
thePersistentIds.stream().map(JpaPid::getId).collect(Collectors.toList());
|
||||
List<Object> objectIds = new ArrayList<>(thePersistentIds);
|
||||
myFullTextSearchSvc.deleteIndexedDocumentsByTypeAndId(ResourceTable.class, objectIds);
|
||||
ourLog.info("Cleared Hibernate Search indexes.");
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ import jakarta.persistence.GenerationType;
|
|||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Index;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.JoinColumns;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.SequenceGenerator;
|
||||
import jakarta.persistence.Table;
|
||||
|
@ -79,6 +80,12 @@ public class MdmLink extends AuditableBasePartitionable implements IMdmLink<JpaP
|
|||
private static final int MATCH_RESULT_LENGTH = 16;
|
||||
private static final int LINK_SOURCE_LENGTH = 16;
|
||||
public static final int SOURCE_TYPE_LENGTH = 40;
|
||||
public static final String GOLDEN_RESOURCE_PID = "GOLDEN_RESOURCE_PID";
|
||||
public static final String GOLDEN_RESOURCE_PARTITION_ID = "GOLDEN_RESOURCE_PARTITION_ID";
|
||||
public static final String PERSON_PID = "PERSON_PID";
|
||||
public static final String PERSON_PARTITION_ID = "PERSON_PARTITION_ID";
|
||||
public static final String TARGET_PID = "TARGET_PID";
|
||||
public static final String TARGET_PARTITION_ID = "TARGET_PARTITION_ID";
|
||||
|
||||
@SequenceGenerator(name = "SEQ_EMPI_LINK_ID", sequenceName = "SEQ_EMPI_LINK_ID")
|
||||
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_EMPI_LINK_ID")
|
||||
|
@ -90,31 +97,52 @@ public class MdmLink extends AuditableBasePartitionable implements IMdmLink<JpaP
|
|||
optional = false,
|
||||
fetch = FetchType.LAZY,
|
||||
cascade = {})
|
||||
@JoinColumn(
|
||||
name = "GOLDEN_RESOURCE_PID",
|
||||
referencedColumnName = "RES_ID",
|
||||
foreignKey = @ForeignKey(name = "FK_EMPI_LINK_GOLDEN_RESOURCE"),
|
||||
insertable = false,
|
||||
updatable = false,
|
||||
nullable = false)
|
||||
@JoinColumns(
|
||||
value = {
|
||||
@JoinColumn(
|
||||
name = GOLDEN_RESOURCE_PID,
|
||||
referencedColumnName = "RES_ID",
|
||||
insertable = false,
|
||||
updatable = false,
|
||||
nullable = false),
|
||||
// @JoinColumn(
|
||||
// name = GOLDEN_RESOURCE_PARTITION_ID,
|
||||
// referencedColumnName = "PARTITION_ID",
|
||||
// insertable = false,
|
||||
// updatable = false,
|
||||
// nullable = false)
|
||||
},
|
||||
foreignKey = @ForeignKey(name = "FK_EMPI_LINK_GOLDEN_RESOURCE"))
|
||||
@NotAudited
|
||||
private ResourceTable myGoldenResource;
|
||||
|
||||
@Column(name = "GOLDEN_RESOURCE_PID", nullable = false)
|
||||
@Column(name = GOLDEN_RESOURCE_PID, nullable = false)
|
||||
private Long myGoldenResourcePid;
|
||||
|
||||
@Column(name = GOLDEN_RESOURCE_PARTITION_ID, nullable = true)
|
||||
private Integer myGoldenResourcePartitionId;
|
||||
|
||||
@Deprecated
|
||||
@ManyToOne(
|
||||
optional = false,
|
||||
fetch = FetchType.LAZY,
|
||||
cascade = {})
|
||||
@JoinColumn(
|
||||
name = "PERSON_PID",
|
||||
referencedColumnName = "RES_ID",
|
||||
foreignKey = @ForeignKey(name = "FK_EMPI_LINK_PERSON"),
|
||||
insertable = false,
|
||||
updatable = false,
|
||||
nullable = false)
|
||||
@JoinColumns(
|
||||
value = {
|
||||
@JoinColumn(
|
||||
name = PERSON_PID,
|
||||
referencedColumnName = "RES_ID",
|
||||
insertable = false,
|
||||
updatable = false,
|
||||
nullable = false),
|
||||
// @JoinColumn(
|
||||
// name = PERSON_PARTITION_ID,
|
||||
// referencedColumnName = "PARTITION_ID",
|
||||
// insertable = false,
|
||||
// updatable = false,
|
||||
// nullable = false)
|
||||
},
|
||||
foreignKey = @ForeignKey(name = "FK_EMPI_LINK_PERSON"))
|
||||
@NotAudited
|
||||
private ResourceTable myPerson;
|
||||
|
||||
|
@ -122,23 +150,39 @@ public class MdmLink extends AuditableBasePartitionable implements IMdmLink<JpaP
|
|||
@Column(name = "PERSON_PID", nullable = false)
|
||||
private Long myPersonPid;
|
||||
|
||||
@Deprecated
|
||||
@Column(name = PERSON_PARTITION_ID, nullable = true)
|
||||
private Integer myPersonPartitionId;
|
||||
|
||||
@ManyToOne(
|
||||
optional = false,
|
||||
fetch = FetchType.LAZY,
|
||||
cascade = {})
|
||||
@JoinColumn(
|
||||
name = "TARGET_PID",
|
||||
referencedColumnName = "RES_ID",
|
||||
foreignKey = @ForeignKey(name = "FK_EMPI_LINK_TARGET"),
|
||||
insertable = false,
|
||||
updatable = false,
|
||||
nullable = false)
|
||||
@JoinColumns(
|
||||
value = {
|
||||
@JoinColumn(
|
||||
name = TARGET_PID,
|
||||
referencedColumnName = "RES_ID",
|
||||
insertable = false,
|
||||
updatable = false,
|
||||
nullable = false),
|
||||
// @JoinColumn(
|
||||
// name = TARGET_PARTITION_ID,
|
||||
// referencedColumnName = "PARTITION_ID",
|
||||
// insertable = false,
|
||||
// updatable = false,
|
||||
// nullable = false)
|
||||
},
|
||||
foreignKey = @ForeignKey(name = "FK_EMPI_LINK_TARGET"))
|
||||
@NotAudited
|
||||
private ResourceTable mySource;
|
||||
|
||||
@Column(name = "TARGET_PID", updatable = false, nullable = false)
|
||||
private Long mySourcePid;
|
||||
|
||||
@Column(name = TARGET_PARTITION_ID, updatable = false, nullable = true)
|
||||
private Integer mySourcePartitionId;
|
||||
|
||||
@Column(name = "MATCH_RESULT", nullable = false)
|
||||
@Enumerated(EnumType.ORDINAL)
|
||||
@JdbcTypeCode(SqlTypes.INTEGER)
|
||||
|
@ -210,6 +254,7 @@ public class MdmLink extends AuditableBasePartitionable implements IMdmLink<JpaP
|
|||
setPersonPid(longPid);
|
||||
|
||||
myGoldenResourcePid = longPid;
|
||||
myGoldenResourcePartitionId = theGoldenResourcePid.getPartitionId();
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -221,6 +266,7 @@ public class MdmLink extends AuditableBasePartitionable implements IMdmLink<JpaP
|
|||
@Override
|
||||
public IMdmLink setSourcePersistenceId(JpaPid theSourcePid) {
|
||||
mySourcePid = theSourcePid.getId();
|
||||
mySourcePartitionId = theSourcePid.getPartitionId();
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -230,10 +276,12 @@ public class MdmLink extends AuditableBasePartitionable implements IMdmLink<JpaP
|
|||
|
||||
public MdmLink setGoldenResource(ResourceTable theGoldenResource) {
|
||||
myGoldenResource = theGoldenResource;
|
||||
myGoldenResourcePid = theGoldenResource.getId();
|
||||
myGoldenResourcePid = theGoldenResource.getId().getId();
|
||||
myGoldenResourcePartitionId = theGoldenResource.getPersistentId().getPartitionId();
|
||||
|
||||
myPerson = theGoldenResource;
|
||||
myPersonPid = theGoldenResource.getId();
|
||||
myPersonPid = theGoldenResource.getId().getId();
|
||||
myPersonPartitionId = theGoldenResource.getPersistentId().getPartitionId();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
@ -269,7 +317,8 @@ public class MdmLink extends AuditableBasePartitionable implements IMdmLink<JpaP
|
|||
|
||||
public MdmLink setSource(ResourceTable theSource) {
|
||||
mySource = theSource;
|
||||
mySourcePid = theSource.getId();
|
||||
mySourcePid = theSource.getId().getId();
|
||||
mySourcePartitionId = theSource.getPersistentId().getPartitionId();
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -364,6 +413,7 @@ public class MdmLink extends AuditableBasePartitionable implements IMdmLink<JpaP
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean getEidMatch() {
|
||||
return myEidMatch;
|
||||
}
|
||||
|
@ -395,6 +445,7 @@ public class MdmLink extends AuditableBasePartitionable implements IMdmLink<JpaP
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MdmLink setMdmSourceType(String mdmSourceType) {
|
||||
myMdmSourceType = mdmSourceType;
|
||||
return this;
|
||||
|
@ -417,14 +468,17 @@ public class MdmLink extends AuditableBasePartitionable implements IMdmLink<JpaP
|
|||
.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMdmSourceType() {
|
||||
return myMdmSourceType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getRuleCount() {
|
||||
return myRuleCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MdmLink setRuleCount(Long theRuleCount) {
|
||||
myRuleCount = theRuleCount;
|
||||
return this;
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
package ca.uhn.fhir.jpa.entity;
|
||||
|
||||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
import ca.uhn.fhir.jpa.model.dao.JpaPid;
|
||||
import ca.uhn.fhir.jpa.model.search.SearchStatusEnum;
|
||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.model.api.Include;
|
||||
|
@ -28,6 +29,7 @@ import ca.uhn.fhir.rest.param.HistorySearchStyleEnum;
|
|||
import ca.uhn.fhir.rest.server.util.ICachedSearchDetails;
|
||||
import ca.uhn.fhir.system.HapiSystemProperties;
|
||||
import jakarta.annotation.Nonnull;
|
||||
import jakarta.annotation.Nullable;
|
||||
import jakarta.persistence.Basic;
|
||||
import jakarta.persistence.CascadeType;
|
||||
import jakarta.persistence.Column;
|
||||
|
@ -87,11 +89,11 @@ public class Search implements ICachedSearchDetails, Serializable {
|
|||
public static final int SEARCH_UUID_COLUMN_LENGTH = 48;
|
||||
|
||||
public static final String HFJ_SEARCH = "HFJ_SEARCH";
|
||||
public static final String SEARCH_UUID = "SEARCH_UUID";
|
||||
private static final int MAX_SEARCH_QUERY_STRING = 10000;
|
||||
private static final int FAILURE_MESSAGE_LENGTH = 500;
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(Search.class);
|
||||
public static final String SEARCH_UUID = "SEARCH_UUID";
|
||||
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
@Column(name = "CREATED", nullable = false, updatable = false)
|
||||
|
@ -140,9 +142,11 @@ public class Search implements ICachedSearchDetails, Serializable {
|
|||
@Column(name = "RESOURCE_ID", nullable = true)
|
||||
private Long myResourceId;
|
||||
|
||||
@Column(name = "PARTITION_ID", nullable = true)
|
||||
private Integer myPartitionId;
|
||||
|
||||
@Column(name = "RESOURCE_TYPE", length = 200, nullable = true)
|
||||
private String myResourceType;
|
||||
|
||||
/**
|
||||
* Note that this field may have the request partition IDs prepended to it
|
||||
*/
|
||||
|
@ -150,7 +154,6 @@ public class Search implements ICachedSearchDetails, Serializable {
|
|||
@Basic(fetch = FetchType.LAZY)
|
||||
@Column(name = "SEARCH_QUERY_STRING", nullable = true, updatable = false, length = MAX_SEARCH_QUERY_STRING)
|
||||
private String mySearchQueryString;
|
||||
|
||||
/**
|
||||
* Note that this field may have the request partition IDs prepended to it
|
||||
*/
|
||||
|
@ -190,7 +193,6 @@ public class Search implements ICachedSearchDetails, Serializable {
|
|||
|
||||
@Transient
|
||||
private transient SearchParameterMap mySearchParameterMapTransient;
|
||||
|
||||
/**
|
||||
* This isn't currently persisted in the DB as it's only used for offset mode. We could
|
||||
* change this if needed in the future.
|
||||
|
@ -203,7 +205,6 @@ public class Search implements ICachedSearchDetails, Serializable {
|
|||
*/
|
||||
@Transient
|
||||
private Integer mySizeModeSize;
|
||||
|
||||
/**
|
||||
* This isn't currently persisted in the DB. When there is search criteria defined in the
|
||||
* search parameter, this is used to keep the search criteria type.
|
||||
|
@ -342,14 +343,17 @@ public class Search implements ICachedSearchDetails, Serializable {
|
|||
myPreferredPageSize = thePreferredPageSize;
|
||||
}
|
||||
|
||||
public Long getResourceId() {
|
||||
return myResourceId;
|
||||
@Nullable
|
||||
public JpaPid getResourceId() {
|
||||
return myResourceId != null ? JpaPid.fromId(myResourceId, myPartitionId) : null;
|
||||
}
|
||||
|
||||
public void setResourceId(Long theResourceId) {
|
||||
myResourceId = theResourceId;
|
||||
public void setResourceId(@Nullable JpaPid theResourceId) {
|
||||
myResourceId = theResourceId != null ? theResourceId.getId() : null;
|
||||
myPartitionId = theResourceId != null ? theResourceId.getPartitionId() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getResourceType() {
|
||||
return myResourceType;
|
||||
}
|
||||
|
|
|
@ -60,6 +60,9 @@ public class SearchResult implements Serializable {
|
|||
@Column(name = "RESOURCE_PID", insertable = true, updatable = false, nullable = false)
|
||||
private Long myResourcePid;
|
||||
|
||||
@Column(name = "RESOURCE_PARTITION_ID", insertable = true, updatable = false, nullable = true)
|
||||
private Integer myResourcePartitionId;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
|
@ -81,6 +84,7 @@ public class SearchResult implements Serializable {
|
|||
.append("search", mySearchPid)
|
||||
.append("order", myOrder)
|
||||
.append("resourcePid", myResourcePid)
|
||||
.append("resourcePartitionId", myResourcePartitionId)
|
||||
.toString();
|
||||
}
|
||||
|
||||
|
@ -109,6 +113,14 @@ public class SearchResult implements Serializable {
|
|||
return this;
|
||||
}
|
||||
|
||||
public Integer getResourcePartitionId() {
|
||||
return myResourcePartitionId;
|
||||
}
|
||||
|
||||
public void setResourcePartitionId(Integer theResourcePartitionId) {
|
||||
myResourcePartitionId = theResourcePartitionId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return myResourcePid.hashCode();
|
||||
|
|
|
@ -19,15 +19,11 @@
|
|||
*/
|
||||
package ca.uhn.fhir.jpa.entity;
|
||||
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.ForeignKey;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.OneToOne;
|
||||
import jakarta.persistence.SequenceGenerator;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.persistence.Temporal;
|
||||
|
@ -56,18 +52,9 @@ public class SubscriptionTable {
|
|||
@Column(name = "PID", insertable = false, updatable = false)
|
||||
private Long myId;
|
||||
|
||||
@Column(name = "RES_ID", insertable = false, updatable = false)
|
||||
@Column(name = "RES_ID", nullable = true)
|
||||
private Long myResId;
|
||||
|
||||
@OneToOne()
|
||||
@JoinColumn(
|
||||
name = "RES_ID",
|
||||
insertable = true,
|
||||
updatable = false,
|
||||
referencedColumnName = "RES_ID",
|
||||
foreignKey = @ForeignKey(name = "FK_SUBSC_RESOURCE_ID"))
|
||||
private ResourceTable mySubscriptionResource;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
|
@ -86,12 +73,4 @@ public class SubscriptionTable {
|
|||
public Long getId() {
|
||||
return myId;
|
||||
}
|
||||
|
||||
public ResourceTable getSubscriptionResource() {
|
||||
return mySubscriptionResource;
|
||||
}
|
||||
|
||||
public void setSubscriptionResource(ResourceTable theSubscriptionResource) {
|
||||
mySubscriptionResource = theSubscriptionResource;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
*/
|
||||
package ca.uhn.fhir.jpa.entity;
|
||||
|
||||
import ca.uhn.fhir.jpa.model.entity.BasePartitionable;
|
||||
import ca.uhn.fhir.jpa.model.entity.IdAndPartitionId;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
import ca.uhn.fhir.util.ValidateUtil;
|
||||
import jakarta.annotation.Nonnull;
|
||||
|
@ -29,9 +31,11 @@ import jakarta.persistence.ForeignKey;
|
|||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.IdClass;
|
||||
import jakarta.persistence.Index;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.OneToOne;
|
||||
import jakarta.persistence.JoinColumns;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.SequenceGenerator;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.persistence.UniqueConstraint;
|
||||
|
@ -45,7 +49,6 @@ import java.io.Serializable;
|
|||
import static org.apache.commons.lang3.StringUtils.left;
|
||||
import static org.apache.commons.lang3.StringUtils.length;
|
||||
|
||||
// @formatter:off
|
||||
@Table(
|
||||
name = "TRM_CODESYSTEM",
|
||||
uniqueConstraints = {
|
||||
|
@ -58,8 +61,8 @@ import static org.apache.commons.lang3.StringUtils.length;
|
|||
@Index(name = "FK_TRMCODESYSTEM_CURVER", columnList = "CURRENT_VERSION_PID")
|
||||
})
|
||||
@Entity()
|
||||
// @formatter:on
|
||||
public class TermCodeSystem implements Serializable {
|
||||
@IdClass(IdAndPartitionId.class)
|
||||
public class TermCodeSystem extends BasePartitionable implements Serializable {
|
||||
public static final int MAX_URL_LENGTH = 200;
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final int MAX_NAME_LENGTH = 200;
|
||||
|
@ -67,33 +70,62 @@ public class TermCodeSystem implements Serializable {
|
|||
@Column(name = "CODE_SYSTEM_URI", nullable = false, length = MAX_URL_LENGTH)
|
||||
private String myCodeSystemUri;
|
||||
|
||||
@OneToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(
|
||||
name = "CURRENT_VERSION_PID",
|
||||
referencedColumnName = "PID",
|
||||
nullable = true,
|
||||
/**
|
||||
* Note that this uses a separate partition_id column because it needs
|
||||
* to be nullable, unlike the PK one which has to be non-nullable
|
||||
* when we're including partition IDs in PKs.
|
||||
*/
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumns(
|
||||
value = {
|
||||
@JoinColumn(
|
||||
name = "CURRENT_VERSION_PID",
|
||||
referencedColumnName = "PID",
|
||||
insertable = false,
|
||||
updatable = false,
|
||||
nullable = true),
|
||||
// @JoinColumn(
|
||||
// name = "CURRENT_VERSION_PARTITION_ID",
|
||||
// referencedColumnName = "PARTITION_ID",
|
||||
// insertable = false,
|
||||
// updatable = false,
|
||||
// nullable = true)
|
||||
},
|
||||
foreignKey = @ForeignKey(name = "FK_TRMCODESYSTEM_CURVER"))
|
||||
private TermCodeSystemVersion myCurrentVersion;
|
||||
|
||||
@Column(name = "CURRENT_VERSION_PID", nullable = true, insertable = false, updatable = false)
|
||||
@Column(name = "CURRENT_VERSION_PID", nullable = true, insertable = true, updatable = true)
|
||||
private Long myCurrentVersionPid;
|
||||
|
||||
@Column(name = "CURRENT_VERSION_PARTITION_ID", nullable = true, insertable = true, updatable = true)
|
||||
private Integer myCurrentVersionPartitionId;
|
||||
|
||||
@Id()
|
||||
@SequenceGenerator(name = "SEQ_CODESYSTEM_PID", sequenceName = "SEQ_CODESYSTEM_PID")
|
||||
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_CODESYSTEM_PID")
|
||||
@Column(name = "PID")
|
||||
private Long myPid;
|
||||
private Long myId;
|
||||
|
||||
@OneToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(
|
||||
name = "RES_ID",
|
||||
referencedColumnName = "RES_ID",
|
||||
nullable = false,
|
||||
updatable = true,
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumns(
|
||||
value = {
|
||||
@JoinColumn(
|
||||
name = "RES_ID",
|
||||
referencedColumnName = "RES_ID",
|
||||
nullable = false,
|
||||
updatable = false,
|
||||
insertable = false),
|
||||
// @JoinColumn(
|
||||
// name = "PARTITION_ID",
|
||||
// referencedColumnName = "PARTITION_ID",
|
||||
// nullable = false,
|
||||
// updatable = false,
|
||||
// insertable = false)
|
||||
},
|
||||
foreignKey = @ForeignKey(name = "FK_TRMCODESYSTEM_RES"))
|
||||
private ResourceTable myResource;
|
||||
|
||||
@Column(name = "RES_ID", insertable = false, updatable = false)
|
||||
@Column(name = "RES_ID", nullable = false)
|
||||
private Long myResourcePid;
|
||||
|
||||
@Column(name = "CS_NAME", nullable = true, length = MAX_NAME_LENGTH)
|
||||
|
@ -158,12 +190,25 @@ public class TermCodeSystem implements Serializable {
|
|||
}
|
||||
|
||||
public TermCodeSystem setCurrentVersion(TermCodeSystemVersion theCurrentVersion) {
|
||||
myCurrentVersion = theCurrentVersion;
|
||||
if (theCurrentVersion == null) {
|
||||
myCurrentVersion = null;
|
||||
myCurrentVersionPid = null;
|
||||
myCurrentVersionPartitionId = null;
|
||||
} else {
|
||||
myCurrentVersion = theCurrentVersion;
|
||||
myCurrentVersionPid = theCurrentVersion.getPid();
|
||||
assert myCurrentVersionPid != null;
|
||||
myCurrentVersionPartitionId = theCurrentVersion.getPartitionId().getPartitionId();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Long getPid() {
|
||||
return myPid;
|
||||
return myId;
|
||||
}
|
||||
|
||||
public IdAndPartitionId getPartitionedId() {
|
||||
return IdAndPartitionId.forId(myId, this);
|
||||
}
|
||||
|
||||
public ResourceTable getResource() {
|
||||
|
@ -172,13 +217,15 @@ public class TermCodeSystem implements Serializable {
|
|||
|
||||
public TermCodeSystem setResource(ResourceTable theResource) {
|
||||
myResource = theResource;
|
||||
myResourcePid = theResource.getId().getId();
|
||||
setPartitionId(theResource.getPartitionId());
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
ToStringBuilder b = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE);
|
||||
b.append("pid", myPid);
|
||||
b.append("pid", myId);
|
||||
b.append("codeSystemUri", myCodeSystemUri);
|
||||
b.append("currentVersionPid", myCurrentVersionPid);
|
||||
b.append("resourcePid", myResourcePid);
|
||||
|
|
|
@ -19,8 +19,12 @@
|
|||
*/
|
||||
package ca.uhn.fhir.jpa.entity;
|
||||
|
||||
import ca.uhn.fhir.jpa.model.entity.BasePartitionable;
|
||||
import ca.uhn.fhir.jpa.model.entity.IdAndPartitionId;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
import ca.uhn.fhir.util.ValidateUtil;
|
||||
import jakarta.annotation.Nonnull;
|
||||
import jakarta.annotation.Nullable;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.FetchType;
|
||||
|
@ -28,11 +32,12 @@ import jakarta.persistence.ForeignKey;
|
|||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.IdClass;
|
||||
import jakarta.persistence.Index;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.JoinColumns;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.OneToMany;
|
||||
import jakarta.persistence.OneToOne;
|
||||
import jakarta.persistence.SequenceGenerator;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.persistence.UniqueConstraint;
|
||||
|
@ -60,7 +65,8 @@ import static org.apache.commons.lang3.StringUtils.length;
|
|||
@Index(name = "FK_CODESYSVER_CS_ID", columnList = "CODESYSTEM_PID")
|
||||
})
|
||||
@Entity()
|
||||
public class TermCodeSystemVersion implements Serializable {
|
||||
@IdClass(IdAndPartitionId.class)
|
||||
public class TermCodeSystemVersion extends BasePartitionable implements Serializable {
|
||||
public static final String IDX_CODESYSTEM_AND_VER = "IDX_CODESYSTEM_AND_VER";
|
||||
public static final int MAX_VERSION_LENGTH = 200;
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
@ -68,22 +74,32 @@ public class TermCodeSystemVersion implements Serializable {
|
|||
@OneToMany(fetch = FetchType.LAZY, mappedBy = "myCodeSystem")
|
||||
private Collection<TermConcept> myConcepts;
|
||||
|
||||
@Id()
|
||||
@Id
|
||||
@SequenceGenerator(name = "SEQ_CODESYSTEMVER_PID", sequenceName = "SEQ_CODESYSTEMVER_PID")
|
||||
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_CODESYSTEMVER_PID")
|
||||
@Column(name = "PID")
|
||||
private Long myId;
|
||||
|
||||
@OneToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(
|
||||
name = "RES_ID",
|
||||
referencedColumnName = "RES_ID",
|
||||
nullable = false,
|
||||
updatable = false,
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumns(
|
||||
value = {
|
||||
@JoinColumn(
|
||||
name = "RES_ID",
|
||||
referencedColumnName = "RES_ID",
|
||||
nullable = false,
|
||||
insertable = false,
|
||||
updatable = false),
|
||||
// @JoinColumn(
|
||||
// name = "PARTITION_ID",
|
||||
// referencedColumnName = "PARTITION_ID",
|
||||
// nullable = false,
|
||||
// insertable = false,
|
||||
// updatable = false)
|
||||
},
|
||||
foreignKey = @ForeignKey(name = "FK_CODESYSVER_RES_ID"))
|
||||
private ResourceTable myResource;
|
||||
|
||||
@Column(name = "RES_ID", nullable = false, insertable = false, updatable = false)
|
||||
@Column(name = "RES_ID", nullable = false)
|
||||
private Long myResourcePid;
|
||||
|
||||
@Column(name = "CS_VERSION_ID", nullable = true, updatable = true, length = MAX_VERSION_LENGTH)
|
||||
|
@ -94,20 +110,27 @@ public class TermCodeSystemVersion implements Serializable {
|
|||
* issued. It should be made non-nullable at some point.
|
||||
*/
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(
|
||||
name = "CODESYSTEM_PID",
|
||||
referencedColumnName = "PID",
|
||||
nullable = true,
|
||||
@JoinColumns(
|
||||
value = {
|
||||
@JoinColumn(
|
||||
name = "CODESYSTEM_PID",
|
||||
referencedColumnName = "PID",
|
||||
insertable = false,
|
||||
updatable = false,
|
||||
nullable = true),
|
||||
// @JoinColumn(
|
||||
// name = "PARTITION_ID",
|
||||
// referencedColumnName = "PARTITION_ID",
|
||||
// insertable = false,
|
||||
// nullable = true,
|
||||
// updatable = false)
|
||||
},
|
||||
foreignKey = @ForeignKey(name = "FK_CODESYSVER_CS_ID"))
|
||||
private TermCodeSystem myCodeSystem;
|
||||
|
||||
@Column(name = "CODESYSTEM_PID", insertable = false, updatable = false)
|
||||
@Column(name = "CODESYSTEM_PID", insertable = true, updatable = true, nullable = true)
|
||||
private Long myCodeSystemPid;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@OneToOne(mappedBy = "myCurrentVersion", optional = true, fetch = FetchType.LAZY)
|
||||
private TermCodeSystem myCodeSystemHavingThisVersionAsCurrentVersionIfAny;
|
||||
|
||||
@Column(name = "CS_DISPLAY", nullable = true, updatable = true, length = MAX_VERSION_LENGTH)
|
||||
private String myCodeSystemDisplayName;
|
||||
|
||||
|
@ -124,6 +147,8 @@ public class TermCodeSystemVersion implements Serializable {
|
|||
|
||||
public TermCodeSystemVersion setCodeSystem(TermCodeSystem theCodeSystem) {
|
||||
myCodeSystem = theCodeSystem;
|
||||
myCodeSystemPid = theCodeSystem.getPid();
|
||||
assert myCodeSystemPid != null;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -147,16 +172,24 @@ public class TermCodeSystemVersion implements Serializable {
|
|||
return myConcepts;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Long getPid() {
|
||||
return myId;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public IdAndPartitionId getId() {
|
||||
return IdAndPartitionId.forId(myId, this);
|
||||
}
|
||||
|
||||
public ResourceTable getResource() {
|
||||
return myResource;
|
||||
}
|
||||
|
||||
public TermCodeSystemVersion setResource(ResourceTable theResource) {
|
||||
myResource = theResource;
|
||||
myResourcePid = theResource.getId().getId();
|
||||
setPartitionId(theResource.getPartitionId());
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,11 +21,14 @@ package ca.uhn.fhir.jpa.entity;
|
|||
|
||||
import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink.RelationshipTypeEnum;
|
||||
import ca.uhn.fhir.jpa.model.entity.EntityIndexStatusEnum;
|
||||
import ca.uhn.fhir.jpa.model.entity.PartitionablePartitionId;
|
||||
import ca.uhn.fhir.jpa.search.DeferConceptIndexingRoutingBinder;
|
||||
import ca.uhn.fhir.util.ValidateUtil;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import jakarta.annotation.Nonnull;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Embeddable;
|
||||
import jakarta.persistence.EmbeddedId;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.EnumType;
|
||||
import jakarta.persistence.Enumerated;
|
||||
|
@ -33,9 +36,9 @@ import jakarta.persistence.FetchType;
|
|||
import jakarta.persistence.ForeignKey;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Index;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.JoinColumns;
|
||||
import jakarta.persistence.Lob;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.OneToMany;
|
||||
|
@ -56,8 +59,16 @@ import org.hibernate.Length;
|
|||
import org.hibernate.annotations.JdbcTypeCode;
|
||||
import org.hibernate.search.engine.backend.types.Projectable;
|
||||
import org.hibernate.search.engine.backend.types.Searchable;
|
||||
import org.hibernate.search.mapper.pojo.bridge.IdentifierBridge;
|
||||
import org.hibernate.search.mapper.pojo.bridge.ValueBridge;
|
||||
import org.hibernate.search.mapper.pojo.bridge.mapping.annotation.IdentifierBridgeRef;
|
||||
import org.hibernate.search.mapper.pojo.bridge.mapping.annotation.PropertyBinderRef;
|
||||
import org.hibernate.search.mapper.pojo.bridge.mapping.annotation.RoutingBinderRef;
|
||||
import org.hibernate.search.mapper.pojo.bridge.mapping.annotation.ValueBridgeRef;
|
||||
import org.hibernate.search.mapper.pojo.bridge.runtime.IdentifierBridgeFromDocumentIdentifierContext;
|
||||
import org.hibernate.search.mapper.pojo.bridge.runtime.IdentifierBridgeToDocumentIdentifierContext;
|
||||
import org.hibernate.search.mapper.pojo.bridge.runtime.ValueBridgeToIndexedValueContext;
|
||||
import org.hibernate.search.mapper.pojo.mapping.definition.annotation.DocumentId;
|
||||
import org.hibernate.search.mapper.pojo.mapping.definition.annotation.FullTextField;
|
||||
import org.hibernate.search.mapper.pojo.mapping.definition.annotation.GenericField;
|
||||
import org.hibernate.search.mapper.pojo.mapping.definition.annotation.Indexed;
|
||||
|
@ -71,6 +82,7 @@ import java.util.Collection;
|
|||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
@ -118,16 +130,27 @@ public class TermConcept implements Serializable {
|
|||
private Date myUpdated;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(
|
||||
name = "CODESYSTEM_PID",
|
||||
nullable = false,
|
||||
referencedColumnName = "PID",
|
||||
@JoinColumns(
|
||||
value = {
|
||||
@JoinColumn(
|
||||
name = "CODESYSTEM_PID",
|
||||
insertable = false,
|
||||
updatable = false,
|
||||
nullable = false,
|
||||
referencedColumnName = "PID"),
|
||||
// @JoinColumn(
|
||||
// name = "PARTITION_ID",
|
||||
// referencedColumnName = "PARTITION_ID",
|
||||
// insertable = false,
|
||||
// updatable = false,
|
||||
// nullable = false)
|
||||
},
|
||||
foreignKey = @ForeignKey(name = "FK_CONCEPT_PID_CS_PID"))
|
||||
private TermCodeSystemVersion myCodeSystem;
|
||||
|
||||
@Column(name = "CODESYSTEM_PID", insertable = false, updatable = false, nullable = false)
|
||||
@Column(name = "CODESYSTEM_PID", insertable = true, updatable = false, nullable = false)
|
||||
@GenericField(name = "myCodeSystemVersionPid")
|
||||
private long myCodeSystemVersionPid;
|
||||
private Long myCodeSystemVersionPid;
|
||||
|
||||
@Column(name = "DISPLAY", nullable = true, length = MAX_DESC_LENGTH)
|
||||
@FullTextField(
|
||||
|
@ -164,12 +187,16 @@ public class TermConcept implements Serializable {
|
|||
@OneToMany(mappedBy = "myConcept", orphanRemoval = false, fetch = FetchType.LAZY)
|
||||
private Collection<TermConceptDesignation> myDesignations;
|
||||
|
||||
@Id
|
||||
@SequenceGenerator(name = "SEQ_CONCEPT_PID", sequenceName = "SEQ_CONCEPT_PID")
|
||||
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_CONCEPT_PID")
|
||||
@Column(name = "PID")
|
||||
@GenericField
|
||||
private Long myId;
|
||||
@EmbeddedId
|
||||
@DocumentId(identifierBridge = @IdentifierBridgeRef(type = TermConceptPkIdentifierBridge.class))
|
||||
@GenericField(
|
||||
name = "myId",
|
||||
projectable = Projectable.YES,
|
||||
valueBridge = @ValueBridgeRef(type = TermConceptPkValueBridge.class))
|
||||
private TermConceptPk myId;
|
||||
|
||||
@Column(name = PartitionablePartitionId.PARTITION_ID, nullable = true, insertable = false, updatable = false)
|
||||
private Integer myPartitionIdValue;
|
||||
|
||||
/**
|
||||
* See {@link EntityIndexStatusEnum} for values
|
||||
|
@ -323,6 +350,8 @@ public class TermConcept implements Serializable {
|
|||
myCodeSystem = theCodeSystemVersion;
|
||||
if (theCodeSystemVersion != null && theCodeSystemVersion.getPid() != null) {
|
||||
myCodeSystemVersionPid = theCodeSystemVersion.getPid();
|
||||
assert myCodeSystemVersionPid != null;
|
||||
myPartitionIdValue = theCodeSystemVersion.getPartitionId().getPartitionId();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
@ -359,12 +388,19 @@ public class TermConcept implements Serializable {
|
|||
return this;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
public TermConceptPk getPid() {
|
||||
if (myId == null) {
|
||||
myId = new TermConceptPk();
|
||||
}
|
||||
return myId;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return getPid().myId;
|
||||
}
|
||||
|
||||
public TermConcept setId(Long theId) {
|
||||
myId = theId;
|
||||
getPid().myId = theId;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -526,4 +562,76 @@ public class TermConcept implements Serializable {
|
|||
public boolean hasParentPidsLobForTesting() {
|
||||
return nonNull(myParentPids);
|
||||
}
|
||||
|
||||
public PartitionablePartitionId getPartitionId() {
|
||||
return PartitionablePartitionId.with(myPartitionIdValue, null);
|
||||
}
|
||||
|
||||
public static class TermConceptPkValueBridge implements ValueBridge<TermConceptPk, Long> {
|
||||
@Override
|
||||
public Long toIndexedValue(TermConceptPk value, ValueBridgeToIndexedValueContext context) {
|
||||
return value.myId;
|
||||
}
|
||||
}
|
||||
|
||||
public static class TermConceptPkIdentifierBridge implements IdentifierBridge<TermConceptPk> {
|
||||
@Override
|
||||
public String toDocumentIdentifier(
|
||||
TermConceptPk propertyValue, IdentifierBridgeToDocumentIdentifierContext context) {
|
||||
return Long.toString(propertyValue.myId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TermConceptPk fromDocumentIdentifier(
|
||||
String documentIdentifier, IdentifierBridgeFromDocumentIdentifierContext context) {
|
||||
TermConceptPk retVal = new TermConceptPk();
|
||||
retVal.myId = Long.parseLong(documentIdentifier);
|
||||
return retVal;
|
||||
}
|
||||
}
|
||||
|
||||
@Embeddable
|
||||
public static class TermConceptPk implements Serializable {
|
||||
@SequenceGenerator(name = "SEQ_CONCEPT_PID", sequenceName = "SEQ_CONCEPT_PID")
|
||||
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_CONCEPT_PID")
|
||||
@Column(name = "PID")
|
||||
@GenericField(projectable = Projectable.YES)
|
||||
private Long myId;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public TermConceptPk() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public TermConceptPk(Long theId, Integer thePartitionId) {
|
||||
myId = theId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object theO) {
|
||||
if (this == theO) {
|
||||
return true;
|
||||
}
|
||||
if (!(theO instanceof TermConceptPk)) {
|
||||
return false;
|
||||
}
|
||||
TermConceptPk that = (TermConceptPk) theO;
|
||||
return Objects.equals(myId, that.myId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(myId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.valueOf(myId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
*/
|
||||
package ca.uhn.fhir.jpa.entity;
|
||||
|
||||
import ca.uhn.fhir.jpa.model.entity.BasePartitionable;
|
||||
import ca.uhn.fhir.jpa.model.entity.IdAndPartitionId;
|
||||
import ca.uhn.fhir.util.ValidateUtil;
|
||||
import jakarta.annotation.Nonnull;
|
||||
import jakarta.persistence.Column;
|
||||
|
@ -28,9 +30,12 @@ import jakarta.persistence.ForeignKey;
|
|||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.IdClass;
|
||||
import jakarta.persistence.Index;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.JoinColumns;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.PrePersist;
|
||||
import jakarta.persistence.SequenceGenerator;
|
||||
import jakarta.persistence.Table;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
|
@ -53,19 +58,35 @@ import static org.apache.commons.lang3.StringUtils.length;
|
|||
@Index(name = "FK_CONCEPTDESIG_CONCEPT", columnList = "CONCEPT_PID", unique = false),
|
||||
@Index(name = "FK_CONCEPTDESIG_CSV", columnList = "CS_VER_PID")
|
||||
})
|
||||
public class TermConceptDesignation implements Serializable {
|
||||
@IdClass(IdAndPartitionId.class)
|
||||
public class TermConceptDesignation extends BasePartitionable implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public static final int MAX_LENGTH = 500;
|
||||
public static final int MAX_VAL_LENGTH = 2000;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(
|
||||
name = "CONCEPT_PID",
|
||||
referencedColumnName = "PID",
|
||||
@JoinColumns(
|
||||
value = {
|
||||
@JoinColumn(
|
||||
name = "CONCEPT_PID",
|
||||
referencedColumnName = "PID",
|
||||
insertable = false,
|
||||
updatable = false,
|
||||
nullable = false),
|
||||
// @JoinColumn(
|
||||
// name = "PARTITION_ID",
|
||||
// referencedColumnName = "PARTITION_ID",
|
||||
// insertable = false,
|
||||
// updatable = false,
|
||||
// nullable = false)
|
||||
},
|
||||
foreignKey = @ForeignKey(name = "FK_CONCEPTDESIG_CONCEPT"))
|
||||
private TermConcept myConcept;
|
||||
|
||||
@Column(name = "CONCEPT_PID", insertable = true, updatable = true, nullable = false)
|
||||
private Long myConceptPid;
|
||||
|
||||
@Id()
|
||||
@SequenceGenerator(name = "SEQ_CONCEPT_DESIG_PID", sequenceName = "SEQ_CONCEPT_DESIG_PID")
|
||||
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_CONCEPT_DESIG_PID")
|
||||
|
@ -95,10 +116,21 @@ public class TermConceptDesignation implements Serializable {
|
|||
* @since 3.5.0
|
||||
*/
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(
|
||||
name = "CS_VER_PID",
|
||||
nullable = true,
|
||||
referencedColumnName = "PID",
|
||||
@JoinColumns(
|
||||
value = {
|
||||
@JoinColumn(
|
||||
name = "CS_VER_PID",
|
||||
insertable = true,
|
||||
updatable = false,
|
||||
nullable = false,
|
||||
referencedColumnName = "PID"),
|
||||
// @JoinColumn(
|
||||
// name = "PARTITION_ID",
|
||||
// referencedColumnName = "PARTITION_ID",
|
||||
// insertable = true,
|
||||
// updatable = false,
|
||||
// nullable = false)
|
||||
},
|
||||
foreignKey = @ForeignKey(name = "FK_CONCEPTDESIG_CSV"))
|
||||
private TermCodeSystemVersion myCodeSystemVersion;
|
||||
|
||||
|
@ -164,13 +196,27 @@ public class TermConceptDesignation implements Serializable {
|
|||
|
||||
public TermConceptDesignation setConcept(TermConcept theConcept) {
|
||||
myConcept = theConcept;
|
||||
myConceptPid = theConcept.getId();
|
||||
setPartitionId(theConcept.getPartitionId());
|
||||
return this;
|
||||
}
|
||||
|
||||
@PrePersist
|
||||
public void prePersist() {
|
||||
if (myConceptPid == null) {
|
||||
myConceptPid = myConcept.getId();
|
||||
assert myConceptPid != null;
|
||||
}
|
||||
}
|
||||
|
||||
public Long getPid() {
|
||||
return myId;
|
||||
}
|
||||
|
||||
public IdAndPartitionId getPartitionedId() {
|
||||
return IdAndPartitionId.forId(myId, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
|
||||
|
@ -183,4 +229,8 @@ public class TermConceptDesignation implements Serializable {
|
|||
.append("value", myValue)
|
||||
.toString();
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return myId;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
*/
|
||||
package ca.uhn.fhir.jpa.entity;
|
||||
|
||||
import ca.uhn.fhir.jpa.model.entity.BasePartitionable;
|
||||
import ca.uhn.fhir.jpa.model.entity.IdAndPartitionId;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
import ca.uhn.fhir.util.ValidateUtil;
|
||||
import jakarta.annotation.Nonnull;
|
||||
|
@ -28,10 +30,12 @@ import jakarta.persistence.ForeignKey;
|
|||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.IdClass;
|
||||
import jakarta.persistence.Index;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.JoinColumns;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.OneToMany;
|
||||
import jakarta.persistence.OneToOne;
|
||||
import jakarta.persistence.SequenceGenerator;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.persistence.UniqueConstraint;
|
||||
|
@ -57,7 +61,8 @@ import static org.apache.commons.lang3.StringUtils.length;
|
|||
// automatically
|
||||
@Index(name = "FK_TRMCONCEPTMAP_RES", columnList = "RES_ID")
|
||||
})
|
||||
public class TermConceptMap implements Serializable {
|
||||
@IdClass(IdAndPartitionId.class)
|
||||
public class TermConceptMap extends BasePartitionable implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
static final int MAX_URL_LENGTH = 200;
|
||||
|
@ -76,16 +81,26 @@ public class TermConceptMap implements Serializable {
|
|||
@Column(name = "PID")
|
||||
private Long myId;
|
||||
|
||||
@OneToOne()
|
||||
@JoinColumn(
|
||||
name = "RES_ID",
|
||||
referencedColumnName = "RES_ID",
|
||||
nullable = false,
|
||||
updatable = false,
|
||||
@ManyToOne()
|
||||
@JoinColumns(
|
||||
value = {
|
||||
@JoinColumn(
|
||||
name = "RES_ID",
|
||||
referencedColumnName = "RES_ID",
|
||||
nullable = false,
|
||||
insertable = false,
|
||||
updatable = false),
|
||||
// @JoinColumn(
|
||||
// name = "PARTITION_ID",
|
||||
// referencedColumnName = "PARTITION_ID",
|
||||
// nullable = false,
|
||||
// insertable = false,
|
||||
// updatable = false)
|
||||
},
|
||||
foreignKey = @ForeignKey(name = "FK_TRMCONCEPTMAP_RES"))
|
||||
private ResourceTable myResource;
|
||||
|
||||
@Column(name = "RES_ID", insertable = false, updatable = false)
|
||||
@Column(name = "RES_ID", nullable = false)
|
||||
private Long myResourcePid;
|
||||
|
||||
@Column(name = "SOURCE_URL", nullable = true, length = TermValueSet.MAX_URL_LENGTH)
|
||||
|
@ -121,15 +136,8 @@ public class TermConceptMap implements Serializable {
|
|||
|
||||
public TermConceptMap setResource(ResourceTable theResource) {
|
||||
myResource = theResource;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Long getResourcePid() {
|
||||
return myResourcePid;
|
||||
}
|
||||
|
||||
public TermConceptMap setResourcePid(Long theResourcePid) {
|
||||
myResourcePid = theResourcePid;
|
||||
myResourcePid = theResource.getId().getId();
|
||||
setPartitionId(theResource.getPartitionId());
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
*/
|
||||
package ca.uhn.fhir.jpa.entity;
|
||||
|
||||
import ca.uhn.fhir.jpa.model.entity.BasePartitionable;
|
||||
import ca.uhn.fhir.jpa.model.entity.IdAndPartitionId;
|
||||
import ca.uhn.fhir.util.ValidateUtil;
|
||||
import jakarta.annotation.Nonnull;
|
||||
import jakarta.persistence.Column;
|
||||
|
@ -27,8 +29,10 @@ import jakarta.persistence.ForeignKey;
|
|||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.IdClass;
|
||||
import jakarta.persistence.Index;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.JoinColumns;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.OneToMany;
|
||||
import jakarta.persistence.SequenceGenerator;
|
||||
|
@ -46,7 +50,8 @@ import static org.apache.commons.lang3.StringUtils.length;
|
|||
@Table(
|
||||
name = "TRM_CONCEPT_MAP_GROUP",
|
||||
indexes = {@Index(name = "FK_TCMGROUP_CONCEPTMAP", columnList = "CONCEPT_MAP_PID")})
|
||||
public class TermConceptMapGroup implements Serializable {
|
||||
@IdClass(IdAndPartitionId.class)
|
||||
public class TermConceptMapGroup extends BasePartitionable implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Id()
|
||||
|
@ -56,10 +61,21 @@ public class TermConceptMapGroup implements Serializable {
|
|||
private Long myId;
|
||||
|
||||
@ManyToOne()
|
||||
@JoinColumn(
|
||||
name = "CONCEPT_MAP_PID",
|
||||
nullable = false,
|
||||
referencedColumnName = "PID",
|
||||
@JoinColumns(
|
||||
value = {
|
||||
@JoinColumn(
|
||||
name = "CONCEPT_MAP_PID",
|
||||
insertable = true,
|
||||
updatable = false,
|
||||
nullable = false,
|
||||
referencedColumnName = "PID"),
|
||||
// @JoinColumn(
|
||||
// name = "PARTITION_ID",
|
||||
// referencedColumnName = "PARTITION_ID",
|
||||
// insertable = true,
|
||||
// updatable = false,
|
||||
// nullable = false)
|
||||
},
|
||||
foreignKey = @ForeignKey(name = "FK_TCMGROUP_CONCEPTMAP"))
|
||||
private TermConceptMap myConceptMap;
|
||||
|
||||
|
@ -93,6 +109,7 @@ public class TermConceptMapGroup implements Serializable {
|
|||
|
||||
public TermConceptMapGroup setConceptMap(TermConceptMap theTermConceptMap) {
|
||||
myConceptMap = theTermConceptMap;
|
||||
setPartitionId(theTermConceptMap.getPartitionId());
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
*/
|
||||
package ca.uhn.fhir.jpa.entity;
|
||||
|
||||
import ca.uhn.fhir.jpa.model.entity.BasePartitionable;
|
||||
import ca.uhn.fhir.jpa.model.entity.IdAndPartitionId;
|
||||
import ca.uhn.fhir.util.ValidateUtil;
|
||||
import jakarta.annotation.Nonnull;
|
||||
import jakarta.persistence.Column;
|
||||
|
@ -27,8 +29,10 @@ import jakarta.persistence.ForeignKey;
|
|||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.IdClass;
|
||||
import jakarta.persistence.Index;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.JoinColumns;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.OneToMany;
|
||||
import jakarta.persistence.SequenceGenerator;
|
||||
|
@ -52,7 +56,8 @@ import static org.apache.commons.lang3.StringUtils.length;
|
|||
@Index(name = "IDX_CNCPT_MAP_GRP_CD", columnList = "SOURCE_CODE"),
|
||||
@Index(name = "FK_TCMGELEMENT_GROUP", columnList = "CONCEPT_MAP_GROUP_PID")
|
||||
})
|
||||
public class TermConceptMapGroupElement implements Serializable {
|
||||
@IdClass(IdAndPartitionId.class)
|
||||
public class TermConceptMapGroupElement extends BasePartitionable implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Id()
|
||||
|
@ -62,10 +67,21 @@ public class TermConceptMapGroupElement implements Serializable {
|
|||
private Long myId;
|
||||
|
||||
@ManyToOne()
|
||||
@JoinColumn(
|
||||
name = "CONCEPT_MAP_GROUP_PID",
|
||||
nullable = false,
|
||||
referencedColumnName = "PID",
|
||||
@JoinColumns(
|
||||
value = {
|
||||
@JoinColumn(
|
||||
name = "CONCEPT_MAP_GROUP_PID",
|
||||
insertable = true,
|
||||
updatable = false,
|
||||
nullable = false,
|
||||
referencedColumnName = "PID"),
|
||||
// @JoinColumn(
|
||||
// name = "PARTITION_ID",
|
||||
// referencedColumnName = "PARTITION_ID",
|
||||
// insertable = true,
|
||||
// updatable = false,
|
||||
// nullable = false)
|
||||
},
|
||||
foreignKey = @ForeignKey(name = "FK_TCMGELEMENT_GROUP"))
|
||||
private TermConceptMapGroup myConceptMapGroup;
|
||||
|
||||
|
@ -110,6 +126,7 @@ public class TermConceptMapGroupElement implements Serializable {
|
|||
|
||||
public TermConceptMapGroupElement setConceptMapGroup(TermConceptMapGroup theTermConceptMapGroup) {
|
||||
myConceptMapGroup = theTermConceptMapGroup;
|
||||
setPartitionId(theTermConceptMapGroup.getPartitionId());
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
*/
|
||||
package ca.uhn.fhir.jpa.entity;
|
||||
|
||||
import ca.uhn.fhir.jpa.model.entity.BasePartitionable;
|
||||
import ca.uhn.fhir.jpa.model.entity.IdAndPartitionId;
|
||||
import ca.uhn.fhir.util.ValidateUtil;
|
||||
import jakarta.annotation.Nonnull;
|
||||
import jakarta.persistence.Column;
|
||||
|
@ -29,8 +31,10 @@ import jakarta.persistence.ForeignKey;
|
|||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.IdClass;
|
||||
import jakarta.persistence.Index;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.JoinColumns;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.SequenceGenerator;
|
||||
import jakarta.persistence.Table;
|
||||
|
@ -53,7 +57,8 @@ import static org.apache.commons.lang3.StringUtils.length;
|
|||
@Index(name = "IDX_CNCPT_MP_GRP_ELM_TGT_CD", columnList = "TARGET_CODE"),
|
||||
@Index(name = "FK_TCMGETARGET_ELEMENT", columnList = "CONCEPT_MAP_GRP_ELM_PID")
|
||||
})
|
||||
public class TermConceptMapGroupElementTarget implements Serializable {
|
||||
@IdClass(IdAndPartitionId.class)
|
||||
public class TermConceptMapGroupElementTarget extends BasePartitionable implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
static final int MAX_EQUIVALENCE_LENGTH = 50;
|
||||
|
@ -65,10 +70,21 @@ public class TermConceptMapGroupElementTarget implements Serializable {
|
|||
private Long myId;
|
||||
|
||||
@ManyToOne()
|
||||
@JoinColumn(
|
||||
name = "CONCEPT_MAP_GRP_ELM_PID",
|
||||
nullable = false,
|
||||
referencedColumnName = "PID",
|
||||
@JoinColumns(
|
||||
value = {
|
||||
@JoinColumn(
|
||||
name = "CONCEPT_MAP_GRP_ELM_PID",
|
||||
insertable = true,
|
||||
updatable = false,
|
||||
nullable = false,
|
||||
referencedColumnName = "PID"),
|
||||
// @JoinColumn(
|
||||
// name = "PARTITION_ID",
|
||||
// referencedColumnName = "PARTITION_ID",
|
||||
// insertable = true,
|
||||
// updatable = false,
|
||||
// nullable = false)
|
||||
},
|
||||
foreignKey = @ForeignKey(name = "FK_TCMGETARGET_ELEMENT"))
|
||||
private TermConceptMapGroupElement myConceptMapGroupElement;
|
||||
|
||||
|
@ -115,6 +131,7 @@ public class TermConceptMapGroupElementTarget implements Serializable {
|
|||
|
||||
public void setConceptMapGroupElement(TermConceptMapGroupElement theTermConceptMapGroupElement) {
|
||||
myConceptMapGroupElement = theTermConceptMapGroupElement;
|
||||
setPartitionId(theTermConceptMapGroupElement.getPartitionId());
|
||||
}
|
||||
|
||||
public String getConceptMapUrl() {
|
||||
|
|
|
@ -19,7 +19,10 @@
|
|||
*/
|
||||
package ca.uhn.fhir.jpa.entity;
|
||||
|
||||
import ca.uhn.fhir.jpa.model.entity.PartitionablePartitionId;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Embeddable;
|
||||
import jakarta.persistence.EmbeddedId;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.EnumType;
|
||||
import jakarta.persistence.Enumerated;
|
||||
|
@ -27,17 +30,22 @@ import jakarta.persistence.FetchType;
|
|||
import jakarta.persistence.ForeignKey;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Index;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.JoinColumns;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.PrePersist;
|
||||
import jakarta.persistence.SequenceGenerator;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.persistence.Transient;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
import org.hibernate.annotations.JdbcTypeCode;
|
||||
import org.hibernate.search.mapper.pojo.mapping.definition.annotation.FullTextField;
|
||||
import org.hibernate.type.SqlTypes;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
|
||||
@Entity
|
||||
@Table(
|
||||
|
@ -53,42 +61,79 @@ public class TermConceptParentChildLink implements Serializable {
|
|||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(
|
||||
name = "CHILD_PID",
|
||||
nullable = false,
|
||||
referencedColumnName = "PID",
|
||||
@JoinColumns(
|
||||
value = {
|
||||
@JoinColumn(
|
||||
name = "CHILD_PID",
|
||||
insertable = false,
|
||||
updatable = false,
|
||||
nullable = false,
|
||||
referencedColumnName = "PID"),
|
||||
// @JoinColumn(
|
||||
// name = "PARTITION_ID",
|
||||
// referencedColumnName = "PARTITION_ID",
|
||||
// insertable = false,
|
||||
// updatable = false,
|
||||
// nullable = false)
|
||||
},
|
||||
foreignKey = @ForeignKey(name = "FK_TERM_CONCEPTPC_CHILD"))
|
||||
private TermConcept myChild;
|
||||
|
||||
@Column(name = "CHILD_PID", insertable = false, updatable = false)
|
||||
@Column(name = "CHILD_PID", insertable = true, updatable = true, nullable = false)
|
||||
private Long myChildPid;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "CODESYSTEM_PID", nullable = false, foreignKey = @ForeignKey(name = "FK_TERM_CONCEPTPC_CS"))
|
||||
@JoinColumns(
|
||||
value = {
|
||||
@JoinColumn(
|
||||
name = "CODESYSTEM_PID",
|
||||
referencedColumnName = "PID",
|
||||
insertable = false,
|
||||
updatable = false,
|
||||
nullable = false),
|
||||
// @JoinColumn(
|
||||
// name = "PARTITION_ID",
|
||||
// referencedColumnName = "PARTITION_ID",
|
||||
// insertable = false,
|
||||
// updatable = false,
|
||||
// nullable = false)
|
||||
},
|
||||
foreignKey = @ForeignKey(name = "FK_TERM_CONCEPTPC_CS"))
|
||||
private TermCodeSystemVersion myCodeSystem;
|
||||
|
||||
@Column(name = "CODESYSTEM_PID", insertable = false, updatable = false, nullable = false)
|
||||
@Column(name = "CODESYSTEM_PID", insertable = true, updatable = true, nullable = false)
|
||||
@FullTextField(name = "myCodeSystemVersionPid")
|
||||
private long myCodeSystemVersionPid;
|
||||
private Long myCodeSystemVersionPid;
|
||||
|
||||
@ManyToOne(
|
||||
fetch = FetchType.LAZY,
|
||||
cascade = {})
|
||||
@JoinColumn(
|
||||
name = "PARENT_PID",
|
||||
nullable = false,
|
||||
referencedColumnName = "PID",
|
||||
@JoinColumns(
|
||||
value = {
|
||||
@JoinColumn(
|
||||
name = "PARENT_PID",
|
||||
insertable = false,
|
||||
updatable = false,
|
||||
nullable = false,
|
||||
referencedColumnName = "PID"),
|
||||
// @JoinColumn(
|
||||
// name = "PARTITION_ID",
|
||||
// referencedColumnName = "PARTITION_ID",
|
||||
// insertable = false,
|
||||
// updatable = false,
|
||||
// nullable = false)
|
||||
},
|
||||
foreignKey = @ForeignKey(name = "FK_TERM_CONCEPTPC_PARENT"))
|
||||
private TermConcept myParent;
|
||||
|
||||
@Column(name = "PARENT_PID", insertable = false, updatable = false)
|
||||
@Column(name = "PARENT_PID", insertable = true, updatable = true, nullable = false)
|
||||
private Long myParentPid;
|
||||
|
||||
@Id()
|
||||
@SequenceGenerator(name = "SEQ_CONCEPT_PC_PID", sequenceName = "SEQ_CONCEPT_PC_PID")
|
||||
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_CONCEPT_PC_PID")
|
||||
@Column(name = "PID")
|
||||
private Long myPid;
|
||||
@EmbeddedId
|
||||
private TermConceptParentChildLinkPk myId;
|
||||
|
||||
@Column(name = PartitionablePartitionId.PARTITION_ID, nullable = true, insertable = true, updatable = false)
|
||||
private Integer myPartitionIdValue;
|
||||
|
||||
@Enumerated(EnumType.ORDINAL)
|
||||
@Column(name = "REL_TYPE", length = 5, nullable = true)
|
||||
|
@ -126,8 +171,15 @@ public class TermConceptParentChildLink implements Serializable {
|
|||
return myCodeSystem;
|
||||
}
|
||||
|
||||
public TermConceptParentChildLinkPk getPid() {
|
||||
if (myId == null) {
|
||||
myId = new TermConceptParentChildLinkPk();
|
||||
}
|
||||
return myId;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return myPid;
|
||||
return getPid().myId;
|
||||
}
|
||||
|
||||
public TermConcept getParent() {
|
||||
|
@ -142,6 +194,22 @@ public class TermConceptParentChildLink implements Serializable {
|
|||
return myRelationshipType;
|
||||
}
|
||||
|
||||
@PrePersist
|
||||
public void prePersist() {
|
||||
if (myChildPid == null) {
|
||||
myChildPid = myChild.getId();
|
||||
assert myChildPid != null;
|
||||
}
|
||||
if (myParentPid == null) {
|
||||
myParentPid = myParent.getId();
|
||||
assert myParentPid != null;
|
||||
}
|
||||
if (myCodeSystemVersionPid == null) {
|
||||
myCodeSystemVersionPid = myCodeSystem.getPid();
|
||||
assert myCodeSystemVersionPid != null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
|
@ -155,16 +223,21 @@ public class TermConceptParentChildLink implements Serializable {
|
|||
|
||||
public TermConceptParentChildLink setChild(TermConcept theChild) {
|
||||
myChild = theChild;
|
||||
myChildPid = theChild.getId();
|
||||
return this;
|
||||
}
|
||||
|
||||
public TermConceptParentChildLink setCodeSystem(TermCodeSystemVersion theCodeSystem) {
|
||||
myCodeSystem = theCodeSystem;
|
||||
public TermConceptParentChildLink setCodeSystem(TermCodeSystemVersion theCodeSystemVersion) {
|
||||
myCodeSystem = theCodeSystemVersion;
|
||||
myCodeSystemVersionPid = theCodeSystemVersion.getPid();
|
||||
return this;
|
||||
}
|
||||
|
||||
public TermConceptParentChildLink setParent(TermConcept theParent) {
|
||||
myParent = theParent;
|
||||
myParentPid = theParent.getId();
|
||||
myPartitionIdValue = theParent.getPartitionId().getPartitionId();
|
||||
getPid().myPartitionIdValue = myPartitionIdValue;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -173,9 +246,54 @@ public class TermConceptParentChildLink implements Serializable {
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
|
||||
.append("pid", myId)
|
||||
.append("csvPid", myCodeSystemVersionPid)
|
||||
.append("parentPid", myParentPid)
|
||||
.append("childPid", myChildPid)
|
||||
.append("rel", myRelationshipType)
|
||||
.toString();
|
||||
}
|
||||
|
||||
public enum RelationshipTypeEnum {
|
||||
// ********************************************
|
||||
// IF YOU ADD HERE MAKE SURE ORDER IS PRESERVED
|
||||
ISA
|
||||
}
|
||||
|
||||
@Embeddable
|
||||
public static class TermConceptParentChildLinkPk implements Serializable {
|
||||
|
||||
@SequenceGenerator(name = "SEQ_CONCEPT_PC_PID", sequenceName = "SEQ_CONCEPT_PC_PID")
|
||||
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_CONCEPT_PC_PID")
|
||||
@Column(name = "PID")
|
||||
private Long myId;
|
||||
|
||||
@Transient
|
||||
private Integer myPartitionIdValue;
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(myId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object theO) {
|
||||
if (this == theO) {
|
||||
return true;
|
||||
}
|
||||
if (!(theO instanceof TermConceptParentChildLinkPk)) {
|
||||
return false;
|
||||
}
|
||||
TermConceptParentChildLinkPk that = (TermConceptParentChildLinkPk) theO;
|
||||
return Objects.equals(myId, that.myId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return myPartitionIdValue + "/" + myId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
*/
|
||||
package ca.uhn.fhir.jpa.entity;
|
||||
|
||||
import ca.uhn.fhir.jpa.model.entity.BasePartitionable;
|
||||
import ca.uhn.fhir.jpa.model.entity.IdAndPartitionId;
|
||||
import ca.uhn.fhir.util.ValidateUtil;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import jakarta.annotation.Nonnull;
|
||||
|
@ -31,10 +33,13 @@ import jakarta.persistence.ForeignKey;
|
|||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.IdClass;
|
||||
import jakarta.persistence.Index;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.JoinColumns;
|
||||
import jakarta.persistence.Lob;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.PrePersist;
|
||||
import jakarta.persistence.SequenceGenerator;
|
||||
import jakarta.persistence.Table;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
|
@ -68,31 +73,61 @@ import static org.apache.commons.lang3.StringUtils.length;
|
|||
@Index(name = "FK_CONCEPTPROP_CONCEPT", columnList = "CONCEPT_PID", unique = false),
|
||||
@Index(name = "FK_CONCEPTPROP_CSV", columnList = "CS_VER_PID")
|
||||
})
|
||||
public class TermConceptProperty implements Serializable {
|
||||
@IdClass(IdAndPartitionId.class)
|
||||
public class TermConceptProperty extends BasePartitionable implements Serializable {
|
||||
public static final int MAX_PROPTYPE_ENUM_LENGTH = 6;
|
||||
private static final long serialVersionUID = 1L;
|
||||
public static final int MAX_LENGTH = 500;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(
|
||||
name = "CONCEPT_PID",
|
||||
referencedColumnName = "PID",
|
||||
@JoinColumns(
|
||||
value = {
|
||||
@JoinColumn(
|
||||
name = "CONCEPT_PID",
|
||||
referencedColumnName = "PID",
|
||||
insertable = false,
|
||||
updatable = false,
|
||||
nullable = false),
|
||||
// @JoinColumn(
|
||||
// name = "PARTITION_ID",
|
||||
// referencedColumnName = "PARTITION_ID",
|
||||
// insertable = false,
|
||||
// updatable = false,
|
||||
// nullable = false)
|
||||
},
|
||||
foreignKey = @ForeignKey(name = "FK_CONCEPTPROP_CONCEPT"))
|
||||
private TermConcept myConcept;
|
||||
|
||||
@Column(name = "CONCEPT_PID", insertable = true, updatable = true, nullable = false)
|
||||
private Long myConceptPid;
|
||||
|
||||
/**
|
||||
* TODO: Make this non-null
|
||||
*
|
||||
* @since 3.5.0
|
||||
*/
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(
|
||||
name = "CS_VER_PID",
|
||||
nullable = true,
|
||||
referencedColumnName = "PID",
|
||||
@JoinColumns(
|
||||
value = {
|
||||
@JoinColumn(
|
||||
name = "CS_VER_PID",
|
||||
insertable = false,
|
||||
updatable = false,
|
||||
nullable = false,
|
||||
referencedColumnName = "PID"),
|
||||
// @JoinColumn(
|
||||
// name = "PARTITION_ID",
|
||||
// referencedColumnName = "PARTITION_ID",
|
||||
// insertable = false,
|
||||
// updatable = false,
|
||||
// nullable = false)
|
||||
},
|
||||
foreignKey = @ForeignKey(name = "FK_CONCEPTPROP_CSV"))
|
||||
private TermCodeSystemVersion myCodeSystemVersion;
|
||||
|
||||
@Column(name = "CS_VER_PID")
|
||||
private Long myCodeSystemVersionPid;
|
||||
|
||||
@Id()
|
||||
@SequenceGenerator(name = "SEQ_CONCEPT_PROP_PID", sequenceName = "SEQ_CONCEPT_PROP_PID")
|
||||
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_CONCEPT_PROP_PID")
|
||||
|
@ -255,14 +290,25 @@ public class TermConceptProperty implements Serializable {
|
|||
|
||||
public TermConceptProperty setCodeSystemVersion(TermCodeSystemVersion theCodeSystemVersion) {
|
||||
myCodeSystemVersion = theCodeSystemVersion;
|
||||
myCodeSystemVersionPid = theCodeSystemVersion.getPid();
|
||||
return this;
|
||||
}
|
||||
|
||||
public TermConceptProperty setConcept(TermConcept theConcept) {
|
||||
myConcept = theConcept;
|
||||
myConceptPid = theConcept.getId();
|
||||
setPartitionId(theConcept.getPartitionId());
|
||||
return this;
|
||||
}
|
||||
|
||||
@PrePersist
|
||||
public void prePersist() {
|
||||
if (myConceptPid == null) {
|
||||
myConceptPid = myConcept.getId();
|
||||
assert myConceptPid != null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
|
||||
|
@ -308,6 +354,10 @@ public class TermConceptProperty implements Serializable {
|
|||
return myId;
|
||||
}
|
||||
|
||||
public IdAndPartitionId getPartitionedId() {
|
||||
return IdAndPartitionId.forId(myId, this);
|
||||
}
|
||||
|
||||
public void performLegacyLobSupport(boolean theSupportLegacyLob) {
|
||||
if (!theSupportLegacyLob) {
|
||||
myValueLob = null;
|
||||
|
@ -333,4 +383,8 @@ public class TermConceptProperty implements Serializable {
|
|||
public void setValueBinForTesting(byte[] theValuebin) {
|
||||
myValueBin = theValuebin;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return myId;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
*/
|
||||
package ca.uhn.fhir.jpa.entity;
|
||||
|
||||
import ca.uhn.fhir.jpa.model.entity.BasePartitionable;
|
||||
import ca.uhn.fhir.jpa.model.entity.IdAndPartitionId;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
import ca.uhn.fhir.util.ValidateUtil;
|
||||
import jakarta.annotation.Nonnull;
|
||||
|
@ -31,10 +33,12 @@ import jakarta.persistence.ForeignKey;
|
|||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.IdClass;
|
||||
import jakarta.persistence.Index;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.JoinColumns;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.OneToMany;
|
||||
import jakarta.persistence.OneToOne;
|
||||
import jakarta.persistence.SequenceGenerator;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.persistence.Temporal;
|
||||
|
@ -69,7 +73,8 @@ import static org.apache.commons.lang3.StringUtils.length;
|
|||
@Index(name = "FK_TRMVALUESET_RES", columnList = "RES_ID")
|
||||
})
|
||||
@Entity()
|
||||
public class TermValueSet implements Serializable {
|
||||
@IdClass(IdAndPartitionId.class)
|
||||
public class TermValueSet extends BasePartitionable implements Serializable {
|
||||
public static final int MAX_EXPANSION_STATUS_LENGTH = 50;
|
||||
public static final int MAX_NAME_LENGTH = 200;
|
||||
public static final int MAX_URL_LENGTH = 200;
|
||||
|
@ -88,16 +93,26 @@ public class TermValueSet implements Serializable {
|
|||
@Column(name = "VER", nullable = true, length = MAX_VER_LENGTH)
|
||||
private String myVersion;
|
||||
|
||||
@OneToOne()
|
||||
@JoinColumn(
|
||||
name = "RES_ID",
|
||||
referencedColumnName = "RES_ID",
|
||||
nullable = false,
|
||||
updatable = false,
|
||||
@ManyToOne()
|
||||
@JoinColumns(
|
||||
value = {
|
||||
@JoinColumn(
|
||||
name = "RES_ID",
|
||||
referencedColumnName = "RES_ID",
|
||||
nullable = false,
|
||||
insertable = false,
|
||||
updatable = false),
|
||||
// @JoinColumn(
|
||||
// name = "PARTITION_ID",
|
||||
// referencedColumnName = "PARTITION_ID",
|
||||
// nullable = false,
|
||||
// insertable = false,
|
||||
// updatable = false)
|
||||
},
|
||||
foreignKey = @ForeignKey(name = "FK_TRMVALUESET_RES"))
|
||||
private ResourceTable myResource;
|
||||
|
||||
@Column(name = "RES_ID", insertable = false, updatable = false)
|
||||
@Column(name = "RES_ID", nullable = false)
|
||||
private Long myResourcePid;
|
||||
|
||||
@Column(name = "VSNAME", nullable = true, length = MAX_NAME_LENGTH)
|
||||
|
@ -145,6 +160,10 @@ public class TermValueSet implements Serializable {
|
|||
return myId;
|
||||
}
|
||||
|
||||
public IdAndPartitionId getPartitionedId() {
|
||||
return IdAndPartitionId.forId(myId, this);
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return myUrl;
|
||||
}
|
||||
|
@ -163,6 +182,8 @@ public class TermValueSet implements Serializable {
|
|||
|
||||
public TermValueSet setResource(ResourceTable theResource) {
|
||||
myResource = theResource;
|
||||
myResourcePid = theResource.getId().getId();
|
||||
setPartitionId(theResource.getPartitionId());
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue