Skip to content

feat: TrackedEntity JDBC insert [DHIS2-21378]#24027

Merged
enricocolasante merged 2 commits into
masterfrom
DHIS2-21378-te-insert
Jun 2, 2026
Merged

feat: TrackedEntity JDBC insert [DHIS2-21378]#24027
enricocolasante merged 2 commits into
masterfrom
DHIS2-21378-te-insert

Conversation

@enricocolasante
Copy link
Copy Markdown
Contributor

@enricocolasante enricocolasante commented May 28, 2026

Summary

Phase 4a of the Hibernate→JDBC tracker bundle persist migration (DHIS2-21378): replace the Hibernate-driven insert path for TrackedEntity with a JDBC multi-row INSERT, while leaving all
other entity types and TEAVs on EntityManager until their respective phases.

  • Pre-allocates primary keys from trackedentityinstance_sequence in a single round-trip (select nextval(seq) from generate_series(1, ?)), and assigns the id to the converted DTO before
    staging so any TEAV/changelog code reading convertedDto.getId() sees the final value.
  • Replaces EntityWriteBatch.flush(EntityManager) with flush(EntityManager, Connection). TrackedEntity inserts now go through a chunked multi-row JDBC INSERT (128 rows / statement, 15
    columns including ST_GeomFromText(...,4326) and ::jsonb userinfo); everything else still delegates to em.persist / em.merge.
  • Introduces AbstractTrackerPersister.sequenceName() as the per-subclass opt-in: only TrackedEntityPersister returns "trackedentityinstance_sequence"; Enrollment / TrackerEvent /
    SingleEvent / Relationship return null and keep their current behavior.
  • Updates getTrackedEntityAttributeValueMap to gate the "load existing TEAVs" JPQL on batch.isStagedAsInsert(te) instead of te.getId() == 0, because pre-allocated ids are no longer a
    reliable transient marker.
  • Switches TrackerImportReportTest from H2ControllerIntegrationTestBase to PostgresControllerIntegrationTestBase since ST_GeomFromText and ::jsonb are PostgreSQL-only.

Design notes

  • Flush ordering. batch.flush(em, conn) runs JDBC TE inserts first, then em.flush() (TEAVs, other types), then changelog inserts. TEAVs persisted via em.persist reference a TE that
    is not in the persistence context but carries a pre-allocated id; Hibernate writes the FK from te.getId() without managing the TE. Changelog FKs see the TE row because both run on the
    same Spring-bound connection inside one transaction.
  • Sequence-name interpolation. sequenceName() is concatenated into the SQL (not bound) because PostgreSQL's nextval takes a regclass. Safe — the value is a hardcoded constant on
    each persister subclass, never user input.
  • Defensive guards. bindTrackedEntityRow throws if it encounters a staged TE with id == 0, and assignId throws IllegalStateException for any DTO type the dispatch doesn't yet
    handle — future phases will plug in additional types.

@enricocolasante enricocolasante force-pushed the DHIS2-21378-te-insert branch from f858d0f to 831dd36 Compare May 28, 2026 12:34
@enricocolasante enricocolasante force-pushed the DHIS2-21378-te-insert branch from 831dd36 to 6f5b5db Compare May 29, 2026 09:10
@enricocolasante enricocolasante marked this pull request as ready for review May 29, 2026 12:24
@enricocolasante enricocolasante requested a review from a team as a code owner May 29, 2026 12:24
* one id per CREATE entity in a single round-trip and assigns the id before staging so the flush
* path can emit a multi-row INSERT.
*/
protected abstract String sequenceName();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could we not make this one return null by default and make TrackedEntityPersister override it? this way we would get rid of the boilerplate code in the other persisters

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just changed to be this way because this is the skeleton for next steps.
Every persister will need to implement this, so there will be no null returned in the end

@enricocolasante enricocolasante requested a review from a team June 1, 2026 09:25
@enricocolasante enricocolasante enabled auto-merge (squash) June 2, 2026 09:35
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented Jun 2, 2026

@enricocolasante enricocolasante merged commit 4eaf6ba into master Jun 2, 2026
23 checks passed
@enricocolasante enricocolasante deleted the DHIS2-21378-te-insert branch June 2, 2026 09:47
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.

3 participants