Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Cachen indlæses ved kald til "/reload" som beskrevet i driftsvejledningen. Følgende query danner grundlag for at fylde cachen med entiteter fra tabellen SOR2SorEntity. En tilsvarende query er lavet til at indlæse fra SOR2SorShakMap.

SOR2SorEntity:

Code Block
languagesql
linenumberstrue
WITH filtered AS (
  SELECT *
  FROM SOR2SorEntity
  WHERE FromDate > :date_cutoff
  UNION ALL
  SELECT t.*
  FROM SOR2SorEntity t
  JOIN (
    SELECT SorId, MAX(FromDate) AS FromDate
    FROM SOR2SorEntity
    WHERE FromDate <= :date_cutoff
    GROUP BY SorId
  ) m
    ON m.SorId = t.SorId
   AND m.FromDate = t.FromDate
  WHERE t.ToDate IS NULL OR t.ToDate > :date_cutoff
)
SELECT f1.*
FROM filtered f1
JOIN (
  SELECT UniqueCurrentKey, MAX(ValidFrom) AS MaxValidFrom
  FROM filtered
  GROUP BY UniqueCurrentKey
) pick
  ON pick.UniqueCurrentKey = f1.UniqueCurrentKey
 AND pick.MaxValidFrom    = f1.ValidFrom;

SOR2SorShakMap:

Code Block
languagesql
linenumberstrue
SELECT
  t1.ValidFrom,
  t1.FromDate,
  t1.ToDate,
  t1.SorId,
  t1.SorHealthInstitutionSorId,
  t1.ShakId
FROM SOR2SorShakMap t1
JOIN (
  SELECT t2.UniqueCurrentKey, MAX(t2.ValidFrom) AS MaxValidFrom
  FROM SOR2SorShakMap t2
  LEFT JOIN (
    SELECT SorId, MAX(FromDate) AS LatestFromDate
    FROM SOR2SorShakMap
    WHERE SELECT t1.ValidFrom, t1.FromDate, t1.ToDate, t1.SorId, t1.ParentSorId, t1.HealthInstitutionSorId,
       t1.ProviderId, t1.ShakId, t1.EntityName, t1.InstitutionOwnerSorId,
       t1.InstitutionOwnerCvrNumberId, t1.EntityTypeId, t1.EntityTypeName
FROM SOR2SorEntity t1
JOIN (
        SELECT UniqueCurrentKey, MAX(ValidFrom) as MaxValidFrom
        FROM SOR2SorEntity
        WHERE FromDate > :date_cutoff
        OR (FromDate = 
                (
 	                SELECT MAX(FromDate)
                	FROM SOR2SorEntity t3
                	WHERE t3.SorId = SOR2SorEntity.SorId
                    AND FromDate <= :date_cutoff
         GROUP  BY  SorId
   ) latest ON t2.SorId = 
               latest.SorId
  WHERE t2.FromDate > :date_cutoff
     OR (t2.FromDate = latest.LatestFromDate AND (t2.ToDate isIS NULL OR t2.ToDate > :date_cutoff)
        )
        GROUP BY t2.UniqueCurrentKey
) t4
 t2 ON t1.UniqueCurrentKey = t2t4.UniqueCurrentKey
 AND t1.ValidFrom = t2t4.MaxValidFrom
;

Parameteren ":date_cutoff" udfyldes med property "sores.retention.period" som beskrevet i driftsvejledningen. 

...

Bemærk, at der i JOIN-betingelsen også forekommer en  "OR (FromDate =" (linje 9). Dette skyldes, at vi ud over historikken for det angivne dato-interval, også har behov for at sikre os, at seneste gyldige SorEntity - uanset FromDate - også altid er med i indlæsningen. Som eksempel kunne man forestille sig en SorEntity, hvor seneste FromDate lå tre år tilbage, og derfor vil den ikke ligge inden for "FromDate > :date_cutoff", hvis ":date_cutoff" kun var to år tilbage. Glemmer vi denne, risikerer vi derfor at have et "hul" i starten af den periode, som har cut-off date som start.

Til den inderste query tilføjes "AND (ToDate is NULL OR ToDate > :date_cutoff)", da en SorEntity med start udenfor intervallet kun har relevans, hvis den stadig er aktiv inden for intervallet. 

ReplacedSORMap

For SOR2SorEntity bliver der også læst ind, en liste af sorIds som SOR2SorEntity'ens sorId er blevet erstatte med som bruges til operation ReplacedSORMapHenter alle erstatningsrelationer mellem SOR-ID’er fra databasen som en flad liste af parent-child forbindelser med gyldighedsperioder. Listen den laver bliver brugt til at lave relationstræet til hurtig opslag i SoresCache.

Code Block
titlegetSorReplacedByEntities
//public FinderList<SorReplacedByDTO> hele træet af SorId'er, som er blevet erstattet af en given SorId
// Eksempel: Hvis SorId er 101 og vi har denne data struktur:
//   101
//    ├── 102
//getSorReplacedByMap() {
        String query =
      ├── 103
//       └── 104
//    └── 105
//        └── 106
// Vil den returner alle disse [102, 103, 104, 105, 106] SorId'er.
public List<Long> getSorReplacedByEntities(Long sorId) {
"SELECT ReplacedSorId, ReplacedBySorId, FromDate, ToDate " +
     Set<Long> visitedSorIds = new HashSet<>();
    List<Long> result = new ArrayList<>()"FROM SOR2SorReplacedByEntities";
    recursiveFetch(sorId, visitedSorIds, result);
  List<SorReplacedByDTO> sorReplacedByEntities return result;
}

private void recursiveFetch(Long sorId, Set<Long> visitedSorIds, List<Long> result) {= jdbcTemplate.query(query, (rs, rowNum) ->
    // Hvis vi allerede har fundet SorId'et,  returner for at undgå uendelig rekursionnew SorReplacedByDTO(
    // Data'en er ikke cirkulær,  dette burde ikke ske
    if (visitedSorIds.contains(sorId)) {rs.getLong("ReplacedSorId"),
        return;
    }
    visitedSorIdsrs.addgetLong(sorId"ReplacedBySorId");,

    // Find alle SorId'er som er blevet erstattet af den givne SorId
    String query = "SELECT ReplacedBySorId FROM SOR2SorReplacedByEntities WHERE ReplacedSorId = :sorId";
 rs.getDate("FromDate").toLocalDate(),
           HashMap<String, Object> parameters = new HashMap<>();
    parameters.put("sorId", sorId);
    List<Long> replacedByIds = jdbcTemplate.queryForList(query, parameters, Long.class);
    
	// Tilføj de fundet sorId'er til resultatet
    result.addAll(replacedByIds);
    
	// Recursivt kald for hver af de fundne underliggende sorId'er for at finde alle SorId'er i træet rs.getDate("ToDate") != null ? rs.getDate("ToDate").toLocalDate() : null
            )
    for (Long id : replacedByIds) {;

        recursiveFetch(id, visitedSorIds, result)return sorReplacedByEntities;
    }
}