
001/* 002 * #%L 003 * HAPI FHIR JPA Server 004 * %% 005 * Copyright (C) 2014 - 2025 Smile CDR, Inc. 006 * %% 007 * Licensed under the Apache License, Version 2.0 (the "License"); 008 * you may not use this file except in compliance with the License. 009 * You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, software 014 * distributed under the License is distributed on an "AS IS" BASIS, 015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 016 * See the License for the specific language governing permissions and 017 * limitations under the License. 018 * #L% 019 */ 020package ca.uhn.fhir.jpa.dao.data; 021 022import ca.uhn.fhir.jpa.dao.data.custom.IForcedIdQueries; 023import ca.uhn.fhir.jpa.model.dao.JpaPid; 024import ca.uhn.fhir.jpa.model.entity.EntityIndexStatusEnum; 025import ca.uhn.fhir.jpa.model.entity.ResourceTable; 026import org.springframework.data.domain.Pageable; 027import org.springframework.data.domain.Slice; 028import org.springframework.data.jpa.repository.JpaRepository; 029import org.springframework.data.jpa.repository.Modifying; 030import org.springframework.data.jpa.repository.Query; 031import org.springframework.data.repository.query.Param; 032import org.springframework.transaction.annotation.Propagation; 033import org.springframework.transaction.annotation.Transactional; 034 035import java.util.Collection; 036import java.util.Date; 037import java.util.List; 038import java.util.Map; 039import java.util.Optional; 040import java.util.stream.Stream; 041 042@Transactional(propagation = Propagation.MANDATORY) 043public interface IResourceTableDao 044 extends JpaRepository<ResourceTable, JpaPid>, IHapiFhirJpaRepository, IForcedIdQueries { 045 046 @Query("SELECT t.myPid FROM ResourceTable t WHERE t.myDeleted IS NOT NULL") 047 Slice<JpaPid> findIdsOfDeletedResources(Pageable thePageable); 048 049 @Query("SELECT t.myPid FROM ResourceTable t WHERE t.myResourceType = :restype AND t.myDeleted IS NOT NULL") 050 Slice<JpaPid> findIdsOfDeletedResourcesOfType(Pageable thePageable, @Param("restype") String theResourceName); 051 052 @Query( 053 "SELECT t.myPid FROM ResourceTable t WHERE t.myPid.myId = :resid AND t.myResourceType = :restype AND t.myDeleted IS NOT NULL") 054 Slice<JpaPid> findIdsOfDeletedResourcesOfType( 055 Pageable thePageable, @Param("resid") Long theResourceId, @Param("restype") String theResourceName); 056 057 @Query( 058 "SELECT t.myResourceType as type, COUNT(t.myResourceType) as count FROM ResourceTable t GROUP BY t.myResourceType") 059 List<Map<?, ?>> getResourceCounts(); 060 061 @Query( 062 "SELECT t.myPid FROM ResourceTable t WHERE t.myUpdated >= :low AND t.myUpdated <= :high ORDER BY t.myUpdated DESC") 063 Slice<JpaPid> findIdsOfResourcesWithinUpdatedRangeOrderedFromNewest( 064 Pageable thePage, @Param("low") Date theLow, @Param("high") Date theHigh); 065 066 @Query( 067 "SELECT t.myPid FROM ResourceTable t WHERE t.myUpdated >= :low AND t.myUpdated <= :high ORDER BY t.myUpdated ASC") 068 Slice<JpaPid> findIdsOfResourcesWithinUpdatedRangeOrderedFromOldest( 069 Pageable thePage, @Param("low") Date theLow, @Param("high") Date theHigh); 070 071 @Query( 072 "SELECT t.myPid, t.myResourceType, t.myUpdated FROM ResourceTable t WHERE t.myUpdated >= :low AND t.myUpdated <= :high ORDER BY t.myUpdated ASC") 073 Stream<Object[]> streamIdsTypesAndUpdateTimesOfResourcesWithinUpdatedRangeOrderedFromOldest( 074 @Param("low") Date theLow, @Param("high") Date theHigh); 075 076 @Query( 077 "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") 078 Stream<Object[]> streamIdsTypesAndUpdateTimesOfResourcesWithinUpdatedRangeOrderedFromOldestForPartitionIds( 079 @Param("low") Date theLow, 080 @Param("high") Date theHigh, 081 @Param("partition_ids") List<Integer> theRequestPartitionIds); 082 083 @Query( 084 "SELECT t.myPid, t.myResourceType, t.myUpdated FROM ResourceTable t WHERE t.myUpdated >= :low AND t.myUpdated <= :high AND ((:dpid IS NULL AND t.myPartitionIdValue IS NULL) OR (t.myPartitionIdValue = :dpid)) ORDER BY t.myUpdated ASC") 085 Stream<Object[]> streamIdsTypesAndUpdateTimesOfResourcesWithinUpdatedRangeOrderedFromOldestForDefaultPartition( 086 @Param("low") Date theLow, @Param("high") Date theHigh, @Param("dpid") Integer theDefaultPartitionId); 087 088 @Query( 089 "SELECT t.myPid FROM ResourceTable t WHERE t.myUpdated >= :low AND t.myUpdated <= :high AND t.myResourceType = :restype ORDER BY t.myUpdated ASC") 090 Slice<JpaPid> findIdsOfResourcesWithinUpdatedRangeOrderedFromOldest( 091 Pageable thePage, 092 @Param("restype") String theResourceType, 093 @Param("low") Date theLow, 094 @Param("high") Date theHigh); 095 096 @Modifying 097 @Query("UPDATE ResourceTable t SET t.myIndexStatus = :status WHERE t.myPid = :id") 098 void updateIndexStatus(@Param("id") JpaPid theId, @Param("status") EntityIndexStatusEnum theIndexStatus); 099 100 @Modifying 101 @Query("UPDATE ResourceTable t SET t.myUpdated = :updated WHERE t.myPid = :id") 102 void updateLastUpdated(@Param("id") JpaPid theId, @Param("updated") Date theUpdated); 103 104 @Modifying 105 @Query("UPDATE ResourceTable t SET t.myVersion = :version, t.myUpdated = :updated WHERE t.myPid = :id") 106 void updateVersionAndLastUpdated( 107 @Param("id") JpaPid theId, @Param("version") Long theVersion, @Param("updated") Date theUpdated); 108 109 @Modifying 110 @Query("DELETE FROM ResourceTable t WHERE t.myPid = :pid") 111 void deleteByPid(@Param("pid") JpaPid theId); 112 113 /** 114 * This method returns a Collection where each row is an element in the collection. Each element in the collection 115 * 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. 116 */ 117 @Query( 118 "SELECT t.myResourceType, t.myPid.myId, t.myDeleted, t.myPartitionIdValue, t.myPartitionDateValue FROM ResourceTable t WHERE t.myPid.myId IN (:pid)") 119 Collection<Object[]> findLookupFieldsByResourcePid(@Param("pid") List<Long> thePids); 120 121 @Query( 122 "SELECT t.myResourceType, t.myPid.myId, t.myDeleted, t.myPartitionIdValue, t.myPartitionDateValue FROM ResourceTable t WHERE t.myPid IN (:pid)") 123 Collection<Object[]> findLookupFieldsByResourcePidWithPartitionId(@Param("pid") List<JpaPid> thePids); 124 125 /** 126 * This method returns a Collection where each row is an element in the collection. Each element in the collection 127 * 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. 128 */ 129 @Query( 130 "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") 131 Collection<Object[]> findLookupFieldsByResourcePidInPartitionIds( 132 @Param("pid") List<Long> thePids, @Param("partition_id") Collection<Integer> thePartitionId); 133 134 /** 135 * This method returns a Collection where each row is an element in the collection. Each element in the collection 136 * 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. 137 */ 138 @Query( 139 "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)") 140 Collection<Object[]> findLookupFieldsByResourcePidInPartitionIdsOrNullPartition( 141 @Param("pid") List<Long> thePids, @Param("partition_id") Collection<Integer> thePartitionId); 142 143 /** 144 * This method returns a Collection where each row is an element in the collection. Each element in the collection 145 * 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. 146 */ 147 @Query( 148 "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") 149 Collection<Object[]> findLookupFieldsByResourcePidInPartitionNull(@Param("pid") List<Long> thePids); 150 151 @Query("SELECT t.myVersion FROM ResourceTable t WHERE t.myPid = :pid") 152 Long findCurrentVersionByPid(@Param("pid") JpaPid thePid); 153 154 /** 155 * This query will return rows with the following values: 156 * Id (JpaPid), FhirId, ResourceType (Patient, etc), version (long) 157 * Order matters! 158 * 159 * @param pid - list of pids to get versions for 160 */ 161 @Query("SELECT t.myPid, t.myResourceType, t.myFhirId, t.myVersion FROM ResourceTable t WHERE t.myPid IN ( :pid )") 162 Collection<Object[]> getResourceVersionsForPid(@Param("pid") Collection<JpaPid> pid); 163 164 @Query("SELECT t FROM ResourceTable t WHERE t.myPartitionIdValue IS NULL AND t.myPid.myId = :pid") 165 Optional<ResourceTable> readByPartitionIdNull(@Param("pid") Long theResourceId); 166 167 @Query("SELECT t FROM ResourceTable t WHERE t.myPartitionIdValue = :partitionId AND t.myPid.myId = :pid") 168 Optional<ResourceTable> readByPartitionId( 169 @Param("partitionId") int thePartitionId, @Param("pid") Long theResourceId); 170 171 @Query( 172 "SELECT t FROM ResourceTable t WHERE (t.myPartitionIdValue IS NULL OR t.myPartitionIdValue IN (:partitionIds)) AND t.myPid.myId = :pid") 173 Optional<ResourceTable> readByPartitionIdsOrNull( 174 @Param("partitionIds") Collection<Integer> thrValues, @Param("pid") Long theResourceId); 175 176 @Query("SELECT t FROM ResourceTable t WHERE t.myPartitionIdValue IN (:partitionIds) AND t.myPid.myId = :pid") 177 Optional<ResourceTable> readByPartitionIds( 178 @Param("partitionIds") Collection<Integer> thrValues, @Param("pid") Long theResourceId); 179 180 @Query("SELECT t FROM ResourceTable t WHERE t.myPid IN :pids") 181 List<ResourceTable> findAllByIdAndLoadForcedIds(@Param("pids") List<JpaPid> thePids); 182 183 @Query("SELECT t FROM ResourceTable t where t.myResourceType = :restype and t.myFhirId = :fhirId") 184 Optional<ResourceTable> findByTypeAndFhirId( 185 @Param("restype") String theResourceName, @Param("fhirId") String theFhirId); 186 187 /** 188 * @deprecated Use {@link #findById(Object)} 189 */ 190 default Optional<ResourceTable> findById(Long theId) { 191 return findById(JpaPid.fromId(theId)); 192 } 193}