Skip to content

Commit 4e3367c

Browse files
feat: TEAV JDBC insert/update [DHIS2-21378] (#24098)
* feat: TrackedEntity JDBC update [DHIS2-21378] * feat: Enrollment JDBC insert/update [DHIS2-21378] * feat: Tracker event JDBC insert/update [DHIS2-21378] * feat: Single event JDBC insert/update [DHIS2-21378] * feat: Relationship JDBC insert/update [DHIS2-21378] * feat: TEAV JDBC insert/update [DHIS2-21378] * Code review fixes * Fix tests * Fix idScheme issue for TEAV
1 parent f5095c6 commit 4e3367c

19 files changed

Lines changed: 342 additions & 132 deletions

File tree

dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/tracker/export/singleevent/SingleEventChangeLogServiceTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,7 @@ private void updateDataValue(String event, String dataElementUid, String newValu
438438
TrackerImportParams.builder().build(),
439439
TrackerObjects.builder().events(List.of(e)).build()));
440440
});
441+
manager.clear();
441442
}
442443

443444
private void updateEventDates(UID event, Instant newDate) throws IOException {

dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/tracker/export/trackerevent/TrackerEventChangeLogServiceTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,7 @@ private void updateDataValue(String event, String dataElementUid, String newValu
470470
TrackerImportParams.builder().build(),
471471
TrackerObjects.builder().events(List.of(e)).build()));
472472
});
473+
manager.clear();
473474
}
474475

475476
private void updateEventDates(UID event, Instant newDate) throws IOException {

dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/tracker/imports/bundle/EnrollmentImportTest.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import java.util.List;
4343
import java.util.Map;
4444
import java.util.stream.Stream;
45+
import org.hisp.dhis.dbms.DbmsManager;
4546
import org.hisp.dhis.feedback.ForbiddenException;
4647
import org.hisp.dhis.feedback.NotFoundException;
4748
import org.hisp.dhis.program.EnrollmentStatus;
@@ -76,6 +77,7 @@ class EnrollmentImportTest extends PostgresIntegrationTestBase {
7677
@Autowired private NamedParameterJdbcTemplate jdbcTemplate;
7778

7879
private User importUser;
80+
@Autowired private DbmsManager dbmsManager;
7981

8082
@BeforeAll
8183
void setUp() throws IOException {
@@ -88,13 +90,15 @@ void setUp() throws IOException {
8890
@ParameterizedTest
8991
@MethodSource("statuses")
9092
void shouldCorrectlyPopulateCompletedDataWhenCreatingAnEnrollment(EnrollmentStatus status)
91-
throws IOException, ForbiddenException, NotFoundException {
93+
throws IOException, NotFoundException {
9294
TrackerImportParams params = TrackerImportParams.builder().build();
9395
TrackerObjects trackerObjects = testSetup.fromJson("tracker/te_enrollment_event.json");
9496
trackerObjects.getEnrollments().get(0).setStatus(status);
9597

9698
ImportReport importReport = trackerImportService.importTracker(params, trackerObjects);
9799

100+
dbmsManager.clearSession();
101+
98102
assertNoErrors(importReport);
99103

100104
Enrollment enrollment =

dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/tracker/imports/bundle/EventDataValueTest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ void testEventDataValueUpdate() throws IOException {
109109
params.setImportStrategy(TrackerImportStrategy.CREATE_AND_UPDATE);
110110
testSetup.importTrackerData("tracker/event_with_updated_data_values.json", params);
111111

112+
manager.clear();
113+
112114
List<TrackerEvent> updatedEvents = manager.getAll(TrackerEvent.class);
113115
assertEquals(1, updatedEvents.size());
114116
TrackerEvent updatedEvent = manager.get(TrackerEvent.class, updatedEvents.get(0).getUid());

dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/tracker/imports/bundle/LastUpdateImportTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ void shouldUpdateTrackedEntityWhenTrackedEntityIsUpdated() throws IOException {
130130
TrackerImportParams params =
131131
TrackerImportParams.builder().importStrategy(TrackerImportStrategy.UPDATE).build();
132132
testSetup.importTrackerData("tracker/one_te.json", params);
133-
133+
clearSession();
134134
Date lastUpdateAfter = getTrackedEntity().getLastUpdated();
135135

136136
assertTrue(
@@ -753,5 +753,6 @@ private void updateAttributeValue(String attribute, String attributeValue) throw
753753
ImportReport report = trackerImportService.importTracker(params, trackerObjects);
754754

755755
assertNoErrors(report);
756+
dbmsManager.clearSession();
756757
}
757758
}

dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/tracker/imports/bundle/OwnershipTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ void testUpdateEnrollment() throws IOException {
194194
params.setImportStrategy(TrackerImportStrategy.CREATE_AND_UPDATE);
195195
ImportReport updatedReport = trackerImportService.importTracker(params, trackerObjects);
196196
manager.flush();
197+
manager.clear();
197198
assertNoErrors(updatedReport);
198199
assertEquals(1, updatedReport.getStats().getUpdated());
199200
enrollments = manager.getAll(Enrollment.class);

dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/tracker/imports/programrule/ProgramRuleAssignActionTest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,8 @@ void shouldImportEventAndCorrectlyAssignPreviousEventDataValue(
235235

236236
ImportReport importReport = trackerImportService.importTracker(params, trackerObjects);
237237

238+
manager.clear();
239+
238240
List<String> firstEventDataValues = getValueForAssignedDataElement(firstEventUid);
239241
List<String> secondEventDataValues = getValueForAssignedDataElement(secondEventUid);
240242
List<String> thirdEventDataValues = getValueForAssignedDataElement(thirdEventUid);

dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/tracker/imports/validation/EventImportValidationTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,7 @@ void testValidateAndAddNotesToUpdatedEvent() throws IOException {
368368
// When -> Update the event and adds 3 more notes
369369
ImportReport importReport =
370370
createEvent("tracker/validations/events-with-notes-update-data.json");
371+
manager.clear();
371372
// Then
372373
final TrackerEvent event = getEventFromReport(importReport);
373374
assertThat(event.getNotes(), hasSize(6));

dhis-2/dhis-test-web-api/src/test/java/org/hisp/dhis/webapi/controller/tracker/export/event/EventsExportChangeLogsControllerTest.java

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -383,23 +383,41 @@ void shouldGetEventChangeLogsWithSimpleFieldsFilter() {
383383
}
384384

385385
private void updateDataValue(String value) {
386+
String body = createDataValueJson(event, value);
387+
startNewRequestSession();
386388
JsonWebMessage importResponse =
387-
POST("/tracker?async=false&importStrategy=UPDATE", createDataValueJson(event, value))
389+
POST("/tracker?async=false&importStrategy=UPDATE", body)
388390
.content(HttpStatus.OK)
389391
.as(JsonWebMessage.class);
390392
assertEquals(HttpStatus.OK.toString(), importResponse.getStatus());
391393
}
392394

393395
private void updateScheduledAtEventField(String value) {
396+
String body = createScheduledAtEventFieldJson(event, value);
397+
startNewRequestSession();
394398
JsonWebMessage importResponse =
395-
POST(
396-
"/tracker?async=false&importStrategy=UPDATE",
397-
createScheduledAtEventFieldJson(event, value))
399+
POST("/tracker?async=false&importStrategy=UPDATE", body)
398400
.content(HttpStatus.OK)
399401
.as(JsonWebMessage.class);
400402
assertEquals(HttpStatus.OK.toString(), importResponse.getStatus());
401403
}
402404

405+
/**
406+
* Simulates a fresh per-request {@code EntityManager}. {@code /api/tracker/**} is excluded from
407+
* the {@code ConditionalOpenEntityManagerInViewFilter} (OSIV is deliberately off for tracker), so
408+
* its Hibernate session is transaction-scoped: it is opened for the import's
409+
* {@code @Transactional} boundary and closed when that transaction completes, so each {@code
410+
* /tracker} request starts with a fresh persistence context. These MockMvc tests otherwise share
411+
* one thread-bound session across imports; since the tracker importer writes via JDBC (bypassing
412+
* Hibernate), a previous import's now-stale managed entity would linger in the L1 cache and be
413+
* returned to the next import's preheat. Flushing then clearing the session between imports
414+
* reproduces the production per-request isolation.
415+
*/
416+
private void startNewRequestSession() {
417+
dbmsManager.flushSession();
418+
dbmsManager.clearSession();
419+
}
420+
403421
private TrackedEntity trackedEntity() {
404422
TrackedEntity te = trackedEntity(orgUnit);
405423
manager.save(te, false);

dhis-2/dhis-test-web-api/src/test/java/org/hisp/dhis/webapi/controller/tracker/export/singleevent/SingleEventsExportChangeLogsControllerTest.java

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -364,23 +364,38 @@ void shouldGetEventChangeLogsWithSimpleFieldsFilter() {
364364
}
365365

366366
private void updateDataValue(String value) {
367+
String body = createDataValueJson(event, value);
368+
startNewRequestSession();
367369
JsonWebMessage importResponse =
368-
POST("/tracker?async=false&importStrategy=UPDATE", createDataValueJson(event, value))
370+
POST("/tracker?async=false&importStrategy=UPDATE", body)
369371
.content(HttpStatus.OK)
370372
.as(JsonWebMessage.class);
371373
assertEquals(HttpStatus.OK.toString(), importResponse.getStatus());
372374
}
373375

374376
private void updateScheduledAtEventField(String value) {
377+
String body = createScheduledAtEventFieldJson(event, value);
378+
startNewRequestSession();
375379
JsonWebMessage importResponse =
376-
POST(
377-
"/tracker?async=false&importStrategy=UPDATE",
378-
createScheduledAtEventFieldJson(event, value))
380+
POST("/tracker?async=false&importStrategy=UPDATE", body)
379381
.content(HttpStatus.OK)
380382
.as(JsonWebMessage.class);
381383
assertEquals(HttpStatus.OK.toString(), importResponse.getStatus());
382384
}
383385

386+
/**
387+
* Simulates a fresh per-request {@code EntityManager}. Production registers an {@code
388+
* OpenEntityManagerInViewFilter}, so every {@code /tracker} request gets its own Hibernate
389+
* session. These MockMvc tests otherwise share one thread-bound session across imports; since the
390+
* tracker importer writes via JDBC (bypassing Hibernate), a previous import's now-stale managed
391+
* entity would linger in the L1 cache and be returned to the next import's preheat. Flushing then
392+
* clearing the session between imports reproduces the production per-request isolation.
393+
*/
394+
private void startNewRequestSession() {
395+
dbmsManager.flushSession();
396+
dbmsManager.clearSession();
397+
}
398+
384399
private SingleEvent event() {
385400
SingleEvent eventA = new SingleEvent();
386401
eventA.setProgramStage(programStage);

0 commit comments

Comments
 (0)