Skip to content

feat: Single event JDBC insert/update [DHIS2-21378]#24083

Draft
enricocolasante wants to merge 8 commits into
masterfrom
DHIS2-21378-single-event
Draft

feat: Single event JDBC insert/update [DHIS2-21378]#24083
enricocolasante wants to merge 8 commits into
masterfrom
DHIS2-21378-single-event

Conversation

@enricocolasante

@enricocolasante enricocolasante commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

feat: Single event JDBC insert/update DHIS2-21378

Summary

Continues the Hibernate→JDBC tracker import migration (Phase 6) by moving SingleEvent writes off EntityManager and onto raw JDBC, following the same pattern already established for
TrackedEntity, Enrollment and TrackerEvent. SingleEvent mirrors the TrackerEvent shape, writing to the dedicated singleevent table (split out per V2_43_21__split_event_table.sql)
— without enrollmentid (single events aren't tied to an enrollment) and without scheduleddate. This includes cascade-handling for event notes (previously managed by Hibernate via
@OneToMany(cascade=ALL)) and JSON serialization of the eventdatavalues jsonb column. Like TrackerEvent, SingleEvent is not L2-cached, so no cache removal was required.

Changes

EntityWriteBatch — the bulk of the work:

  • SingleEvent inserts are now flushed via a multi-row JDBC INSERT into singleevent. Ids are pre-allocated from singleevent_sequence by AbstractTrackerPersister.
  • SingleEvent updates are flushed via a single JDBC unnest UPDATE against singleevent, writing only the columns mutated by TrackerObjectsMapper.mapSingleEvent on the update
    branch. Insert-only columns (uid, created, createdbyuserinfo, deleted) and externally-owned columns (lastsynchronized) are deliberately excluded.
  • eventdatavalues is serialized as a JSON object keyed by dataElement uid, matching JsonEventDataValueSetBinaryType, so the on-disk shape is byte-identical to the Hibernate-written
    value.
  • SingleEvent notes are cascade-inserted in two further multi-row INSERTs (note and the singleevent_notes join table), replacing Hibernate's cascade behaviour. New note ids are
    allocated from note_sequence; sort_order is derived from the 1-based list position. Notes are append-only on update — only notes with id == 0 are treated as new. The note-row insert
    logic is shared with the enrollment / tracker-event paths via the NoteToInsert abstraction.
  • Applies the same L1-staleness fix used for the other entity types: after the JDBC UPDATE bypasses Hibernate, the preheat-loaded managed SingleEvent is detached so any subsequent
    JPQL read reloads fresh DB state (the reload also picks up the notes appended later in the flush).
  • Removes the now-unused mergeAll helper.

AbstractTrackerPersister:

  • assignId now handles SingleEvent (in addition to TrackedEntity, Enrollment and TrackerEvent) for pre-allocated ids.

SingleEventPersister:

  • sequenceName() now returns singleevent_sequence (was null), enabling id pre-allocation.

Notes

  • Relationship and TEAV writes still delegate to EntityManager; their Phase 6 JDBC replacements follow.
  • Sequence clean-up (to do before/with this PR's merge): per the migration plan, the single-events PR carries the sequence rename for the already-migrated entity types — rename the
    legacy sequences trackedentityinstance_sequence (TrackedEntity) and programinstance_sequence (Enrollment) so all migrated entity types use sequence names matching their current entity
    names.

@enricocolasante enricocolasante force-pushed the DHIS2-21378-single-event branch 3 times, most recently from 8ee78f7 to fdc5b6b Compare June 2, 2026 07:30
@enricocolasante enricocolasante force-pushed the DHIS2-21378-single-event branch from fdc5b6b to b8b8610 Compare June 2, 2026 07:38
@sonarqubecloud

sonarqubecloud Bot commented Jun 9, 2026

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant