Skip to content

Commit e73a382

Browse files
committed
Merge branch '7.2' into 7.3
2 parents a7da59b + f43f14e commit e73a382

12 files changed

+164
-32
lines changed

avni-server-api/src/main/java/org/avni/server/dao/EncounterSearchRepository.java

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,22 @@
33
import org.avni.server.dao.search.EncounterSearchQueryBuilder;
44
import org.avni.server.dao.search.SqlQuery;
55
import org.avni.server.domain.Encounter;
6-
import org.avni.server.framework.security.UserContextHolder;
76
import org.avni.server.web.api.EncounterSearchRequest;
87
import org.springframework.stereotype.Repository;
98

109
import javax.persistence.EntityManager;
11-
import javax.persistence.PersistenceContext;
1210
import javax.persistence.Query;
1311
import javax.transaction.Transactional;
1412
import java.math.BigInteger;
1513
import java.util.List;
1614

1715
@Repository
1816
@Transactional
19-
public class EncounterSearchRepository {
17+
public class EncounterSearchRepository extends RoleSwitchableRepository{
2018

21-
@PersistenceContext
22-
private EntityManager entityManager;
19+
public EncounterSearchRepository(EntityManager entityManager) {
20+
super(entityManager);
21+
}
2322

2423
@Transactional
2524
public List<Encounter> search(EncounterSearchRequest searchRequest) {
@@ -38,16 +37,6 @@ public List<Encounter> search(EncounterSearchRequest searchRequest) {
3837
return resultList;
3938
}
4039

41-
private void setRoleBackToUser() {
42-
Query setRoleBackToWhatever = entityManager.createNativeQuery("set role " + UserContextHolder.getOrganisation().getDbUser());
43-
setRoleBackToWhatever.executeUpdate();
44-
}
45-
46-
private void setRoleToNone() {
47-
Query resetQuery = entityManager.createNativeQuery("reset role;");
48-
resetQuery.executeUpdate();
49-
}
50-
5140
public long getCount(EncounterSearchRequest searchRequest) {
5241
setRoleToNone();
5342

avni-server-api/src/main/java/org/avni/server/dao/LocationMappingRepository.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import org.avni.server.domain.AddressLevel;
44
import org.avni.server.domain.ParentLocationMapping;
5+
import org.avni.server.framework.security.UserContextHolder;
56
import org.springframework.data.domain.Pageable;
67
import org.springframework.data.domain.Page;
78
import org.springframework.data.jpa.repository.Query;
@@ -22,12 +23,14 @@ public interface LocationMappingRepository extends ReferenceDataRepository<Paren
2223
" inner join address_level al1 on al.lineage @> al1.lineage and al.id <> al1.id\n" +
2324
" inner join location_location_mapping llm on al1.id = llm.location_id\n" +
2425
"where c.id = :catchmentId\n" +
26+
" and c.organisation_id = :organisationId\n" +
2527
" and llm.last_modified_date_time between :lastModifiedDateTime and :now\n" +
2628
"order by llm.last_modified_date_time asc, llm.id asc", nativeQuery = true)
2729
Page<ParentLocationMapping> getSyncResults(
2830
long catchmentId,
2931
Date lastModifiedDateTime,
3032
Date now,
33+
long organisationId,
3134
Pageable pageable
3235
);
3336

@@ -43,7 +46,8 @@ Page<ParentLocationMapping> getSyncResults(
4346

4447
@Override
4548
default Page<ParentLocationMapping> getSyncResults(SyncParameters syncParameters) {
46-
return getSyncResults(syncParameters.getCatchment().getId(), syncParameters.getLastModifiedDateTime().toDate(), syncParameters.getNow().toDate(), syncParameters.getPageable());
49+
Long organisationId = UserContextHolder.getOrganisation().getId();
50+
return getSyncResults(syncParameters.getCatchment().getId(), syncParameters.getLastModifiedDateTime().toDate(), syncParameters.getNow().toDate(), organisationId, syncParameters.getPageable());
4751
}
4852

4953
@Override
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package org.avni.server.dao;
2+
3+
import org.avni.server.domain.AddressLevel;
4+
import org.avni.server.domain.ParentLocationMapping;
5+
import org.springframework.data.domain.Page;
6+
import org.springframework.data.domain.Slice;
7+
import org.springframework.stereotype.Repository;
8+
9+
import javax.persistence.EntityManager;
10+
import javax.transaction.Transactional;
11+
12+
/**
13+
* LocationSyncRepository uses the postgres @> keyword for sync, which does not index well and creates poor plans.
14+
* This is a performance enhancement that temporarily switches out the role of the user before running this query.
15+
*
16+
*/
17+
@Repository
18+
public class LocationMappingSyncRepository extends RoleSwitchableRepository implements SyncableRepository<ParentLocationMapping> {
19+
private LocationMappingRepository locationMappingRepository;
20+
21+
public LocationMappingSyncRepository(EntityManager entityManager, LocationMappingRepository locationMappingRepository) {
22+
super(entityManager);
23+
this.locationMappingRepository = locationMappingRepository;
24+
}
25+
26+
@Override
27+
public boolean isEntityChanged(SyncParameters syncParameters) {
28+
return locationMappingRepository.isEntityChanged(syncParameters);
29+
}
30+
31+
@Override
32+
public Slice<ParentLocationMapping> getSyncResultsAsSlice(SyncParameters syncParameters) {
33+
return locationMappingRepository.getSyncResultsAsSlice(syncParameters);
34+
}
35+
36+
37+
@Override
38+
@Transactional
39+
public Page<ParentLocationMapping> getSyncResults(SyncParameters syncParameters) {
40+
try {
41+
setRoleToNone();
42+
Page<ParentLocationMapping> syncResults = locationMappingRepository.getSyncResults(syncParameters);
43+
return syncResults;
44+
} finally {
45+
setRoleBackToUser();
46+
}
47+
}
48+
}

avni-server-api/src/main/java/org/avni/server/dao/LocationRepository.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,10 @@ public interface LocationRepository extends ReferenceDataRepository<AddressLevel
4242
" inner join address_level al on cam.addresslevel_id = al.id\n" +
4343
" inner join address_level al1 on al.lineage @> al1.lineage \n" +
4444
"where c.id = :catchmentId\n" +
45+
" and c.organisation_id = :organisationId\n" +
4546
" and al1.last_modified_date_time between :lastModifiedDateTime and :now\n" +
4647
"order by al1.last_modified_date_time asc, al1.id asc", nativeQuery = true)
47-
Page<AddressLevel> getSyncResults(long catchmentId, Date lastModifiedDateTime, Date now, Pageable pageable);
48+
Page<AddressLevel> getSyncResults(long catchmentId, Date lastModifiedDateTime, Date now, long organisationId, Pageable pageable);
4849

4950
@Query(value = "select count(*)\n" +
5051
"from catchment c\n" +
@@ -105,7 +106,8 @@ public interface LocationRepository extends ReferenceDataRepository<AddressLevel
105106

106107
@Override
107108
default Page<AddressLevel> getSyncResults(SyncParameters syncParameters) {
108-
return getSyncResults(syncParameters.getCatchment().getId(), syncParameters.getLastModifiedDateTime().toDate(), syncParameters.getNow().toDate(), syncParameters.getPageable());
109+
Long organisationId = UserContextHolder.getOrganisation().getId();
110+
return getSyncResults(syncParameters.getCatchment().getId(), syncParameters.getLastModifiedDateTime().toDate(), syncParameters.getNow().toDate(), organisationId, syncParameters.getPageable());
109111
}
110112

111113
@Override
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package org.avni.server.dao;
2+
3+
import org.avni.server.domain.AddressLevel;
4+
import org.springframework.data.domain.Page;
5+
import org.springframework.data.domain.Slice;
6+
import org.springframework.stereotype.Repository;
7+
8+
import javax.persistence.EntityManager;
9+
import javax.transaction.Transactional;
10+
11+
@Repository
12+
public class LocationSyncRepository extends RoleSwitchableRepository implements SyncableRepository<AddressLevel> {
13+
private LocationRepository locationRepository;
14+
15+
public LocationSyncRepository(EntityManager entityManager, LocationRepository locationRepository) {
16+
super(entityManager);
17+
this.locationRepository = locationRepository;
18+
}
19+
20+
@Override
21+
public boolean isEntityChanged(SyncParameters syncParameters) {
22+
return locationRepository.isEntityChanged(syncParameters);
23+
}
24+
25+
@Override
26+
public Slice<AddressLevel> getSyncResultsAsSlice(SyncParameters syncParameters) {
27+
return locationRepository.getSyncResultsAsSlice(syncParameters);
28+
}
29+
30+
@Override
31+
@Transactional
32+
public Page<AddressLevel> getSyncResults(SyncParameters syncParameters) {
33+
try {
34+
setRoleToNone();
35+
Page<AddressLevel> syncResults = locationRepository.getSyncResults(syncParameters);
36+
return syncResults;
37+
} finally {
38+
setRoleBackToUser();
39+
}
40+
}
41+
}

avni-server-api/src/main/java/org/avni/server/dao/OperatingIndividualScopeAwareRepository.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
@SuppressWarnings("rawtypes")
2020
@NoRepositoryBean
21-
public interface OperatingIndividualScopeAwareRepository<T extends CHSEntity> extends JpaSpecificationExecutor<T>, CustomCHSJpaRepository<T, Long> {
21+
public interface OperatingIndividualScopeAwareRepository<T extends CHSEntity> extends JpaSpecificationExecutor<T>, CustomCHSJpaRepository<T, Long>, SyncableRepository<T> {
2222
default Specification getSpecification(SyncParameters syncParameters) {
2323
Specification specification;
2424
if (syncParameters.isModificationCheckOnEntity()) {
@@ -35,16 +35,19 @@ default Specification getSpecification(SyncParameters syncParameters) {
3535
return specification;
3636
}
3737

38+
@Override
3839
default Slice<T> getSyncResultsAsSlice(SyncParameters syncParameters) {
3940
Specification specification = getSpecification(syncParameters);
4041
return findAllAsSlice(specification, syncParameters.getPageable());
4142
}
4243

44+
@Override
4345
default Page<T> getSyncResults(SyncParameters syncParameters) {
4446
Specification specification = getSpecification(syncParameters);
4547
return findAll(specification, syncParameters.getPageable());
4648
}
4749

50+
@Override
4851
boolean isEntityChanged(SyncParameters syncParameters);
4952

5053
default Specification<T> getAuditSpecification(SyncParameters syncParameters) {
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package org.avni.server.dao;
2+
3+
import org.avni.server.framework.security.UserContextHolder;
4+
5+
import javax.persistence.EntityManager;
6+
import javax.persistence.PersistenceContext;
7+
import javax.persistence.Query;
8+
9+
public class RoleSwitchableRepository {
10+
@PersistenceContext
11+
protected EntityManager entityManager;
12+
13+
public RoleSwitchableRepository(EntityManager entityManager) {
14+
this.entityManager = entityManager;
15+
}
16+
17+
protected void setRoleBackToUser() {
18+
Query setRoleBackToWhatever = entityManager.createNativeQuery("set role \"" + UserContextHolder.getOrganisation().getDbUser() + "\"");
19+
setRoleBackToWhatever.executeUpdate();
20+
}
21+
22+
protected void setRoleToNone() {
23+
Query resetQuery = entityManager.createNativeQuery("reset role;");
24+
resetQuery.executeUpdate();
25+
}
26+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package org.avni.server.dao;
2+
3+
import org.springframework.data.domain.Page;
4+
import org.springframework.data.domain.Slice;
5+
6+
public interface SyncableRepository<T> {
7+
Page<T> getSyncResults(SyncParameters syncParameters);
8+
boolean isEntityChanged(SyncParameters syncParameters);
9+
Slice<T> getSyncResultsAsSlice(SyncParameters syncParameters);
10+
}

avni-server-api/src/main/java/org/avni/server/service/ScopeAwareService.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package org.avni.server.service;
22

3-
import org.avni.server.dao.OperatingIndividualScopeAwareRepository;
43
import org.avni.server.dao.SyncParameters;
4+
import org.avni.server.dao.SyncableRepository;
55
import org.avni.server.dao.sync.SyncEntityName;
66
import org.avni.server.domain.CHSEntity;
77
import org.avni.server.domain.SubjectType;
@@ -23,7 +23,7 @@ default boolean isChangedByCatchment(User user, DateTime lastModifiedDateTime, S
2323
return repository().isEntityChanged(new SyncParameters(lastModifiedDateTime, DateTime.now(), null, null, null, null, null, user.getSyncSettings(), syncEntityName, user.getCatchment()));
2424
}
2525

26-
OperatingIndividualScopeAwareRepository<T> repository();
26+
SyncableRepository<T> repository();
2727

2828
boolean isScopeEntityChanged(DateTime lastModifiedDateTime, String typeUUID);
2929
}

avni-server-api/src/main/java/org/avni/server/service/ScopeBasedSyncService.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
package org.avni.server.service;
22

33
import org.avni.server.dao.SyncParameters;
4+
import org.avni.server.dao.SyncableRepository;
45
import org.avni.server.dao.sync.SyncEntityName;
56
import org.avni.server.domain.CHSEntity;
67
import org.avni.server.domain.SubjectType;
78
import org.avni.server.domain.User;
89
import org.joda.time.DateTime;
9-
import org.avni.server.dao.OperatingIndividualScopeAwareRepository;
1010
import org.springframework.data.domain.Page;
1111
import org.springframework.data.domain.Pageable;
1212
import org.springframework.data.domain.Slice;
@@ -22,31 +22,31 @@ public ScopeBasedSyncService(AddressLevelService addressLevelService) {
2222
this.addressLevelService = addressLevelService;
2323
}
2424

25-
public Page<T> getSyncResultsBySubjectTypeRegistrationLocation(OperatingIndividualScopeAwareRepository<T> repository, User user, DateTime lastModifiedDateTime, DateTime now, Long typeId, Pageable pageable, SubjectType subjectType, SyncEntityName syncEntityName) {
25+
public Page<T> getSyncResultsBySubjectTypeRegistrationLocation(SyncableRepository<T> repository, User user, DateTime lastModifiedDateTime, DateTime now, Long typeId, Pageable pageable, SubjectType subjectType, SyncEntityName syncEntityName) {
2626
List<Long> addressLevels = addressLevelService.getAllRegistrationAddressIdsBySubjectType(user.getCatchment(), subjectType);
2727
return repository.getSyncResults(new SyncParameters(lastModifiedDateTime, now, typeId, null, pageable, addressLevels, subjectType, user.getSyncSettings(), syncEntityName, user.getCatchment()));
2828
}
2929

30-
public Page<T> getSyncResultsBySubjectTypeRegistrationLocation(OperatingIndividualScopeAwareRepository<T> repository, User user, DateTime lastModifiedDateTime, DateTime now, String entityTypeUuid, Pageable pageable, SubjectType subjectType, SyncEntityName syncEntityName) {
30+
public Page<T> getSyncResultsBySubjectTypeRegistrationLocation(SyncableRepository<T> repository, User user, DateTime lastModifiedDateTime, DateTime now, String entityTypeUuid, Pageable pageable, SubjectType subjectType, SyncEntityName syncEntityName) {
3131
List<Long> addressLevels = addressLevelService.getAllRegistrationAddressIdsBySubjectType(user.getCatchment(), subjectType);
3232
return repository.getSyncResults(new SyncParameters(lastModifiedDateTime, now, null, entityTypeUuid, pageable, addressLevels, subjectType, user.getSyncSettings(), syncEntityName, user.getCatchment()));
3333
}
3434

35-
public Page<T> getSyncResultsByCatchment(OperatingIndividualScopeAwareRepository<T> repository, User user, DateTime lastModifiedDateTime, DateTime now, Pageable pageable, SyncEntityName syncEntityName) {
35+
public Page<T> getSyncResultsByCatchment(SyncableRepository<T> repository, User user, DateTime lastModifiedDateTime, DateTime now, Pageable pageable, SyncEntityName syncEntityName) {
3636
return repository.getSyncResults(new SyncParameters(lastModifiedDateTime, now, null, null, pageable, null, null, user.getSyncSettings(), syncEntityName, user.getCatchment()));
3737
}
3838

39-
public Slice<T> getSyncResultsBySubjectTypeRegistrationLocationAsSlice(OperatingIndividualScopeAwareRepository<T> repository, User user, DateTime lastModifiedDateTime, DateTime now, Long typeId, Pageable pageable, SubjectType subjectType, SyncEntityName syncEntityName) {
39+
public Slice<T> getSyncResultsBySubjectTypeRegistrationLocationAsSlice(SyncableRepository<T> repository, User user, DateTime lastModifiedDateTime, DateTime now, Long typeId, Pageable pageable, SubjectType subjectType, SyncEntityName syncEntityName) {
4040
List<Long> addressLevels = addressLevelService.getAllRegistrationAddressIdsBySubjectType(user.getCatchment(), subjectType);
4141
return repository.getSyncResultsAsSlice(new SyncParameters(lastModifiedDateTime, now, typeId, null, pageable, addressLevels, subjectType, user.getSyncSettings(), syncEntityName, user.getCatchment()));
4242
}
4343

44-
public Slice<T> getSyncResultsBySubjectTypeRegistrationLocationAsSlice(OperatingIndividualScopeAwareRepository<T> repository, User user, DateTime lastModifiedDateTime, DateTime now, String entityTypeUuid, Pageable pageable, SubjectType subjectType, SyncEntityName syncEntityName) {
44+
public Slice<T> getSyncResultsBySubjectTypeRegistrationLocationAsSlice(SyncableRepository<T> repository, User user, DateTime lastModifiedDateTime, DateTime now, String entityTypeUuid, Pageable pageable, SubjectType subjectType, SyncEntityName syncEntityName) {
4545
List<Long> addressLevels = addressLevelService.getAllRegistrationAddressIdsBySubjectType(user.getCatchment(), subjectType);
4646
return repository.getSyncResultsAsSlice(new SyncParameters(lastModifiedDateTime, now, null, entityTypeUuid, pageable, addressLevels, subjectType, user.getSyncSettings(), syncEntityName, user.getCatchment()));
4747
}
4848

49-
public Slice<T> getSyncResultsByCatchmentAsSlice(OperatingIndividualScopeAwareRepository<T> repository, User user, DateTime lastModifiedDateTime, DateTime now, Pageable pageable, SyncEntityName syncEntityName) {
49+
public Slice<T> getSyncResultsByCatchmentAsSlice(SyncableRepository<T> repository, User user, DateTime lastModifiedDateTime, DateTime now, Pageable pageable, SyncEntityName syncEntityName) {
5050
return repository.getSyncResultsAsSlice(new SyncParameters(lastModifiedDateTime, now, null, null, pageable, null, null, user.getSyncSettings(), syncEntityName, user.getCatchment()));
5151
}
5252
}

0 commit comments

Comments
 (0)