Skip to content

fix: share one connection between Hibernate and JDBC DHIS2-22067 - #25041

Merged
teleivo merged 1 commit into
masterfrom
DHIS2-22067
Sep 8, 2026
Merged

fix: share one connection between Hibernate and JDBC DHIS2-22067#25041
teleivo merged 1 commit into
masterfrom
DHIS2-22067

Conversation

@teleivo

@teleivo teleivo commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

JpaTransactionManager was created without a DataSource, so Spring never registered a ConnectionHolder under the DataSource key. Every @Transactional method mixing Hibernate with a plain JdbcTemplate took a second connection from the same pool which was not enlisted in the transaction: its statements commit immediately and a rollback does not cover them.

Fixed by passing the same injected actualDataSource bean the JdbcTemplates get.

Why it matters: the org unit merge can destroy data. merge() is one transaction over 20 handlers, interleaving Hibernate ones with two raw-JDBC ones that delete datavalue and dataapproval. Those deletes commit as they run, so a later failure (a tracker handler, deleting the sources, an optimistic lock at commit) rolls back the Hibernate work and leaves the source org units present with their data gone. About a dozen handlers run inside that window.

Introduced in 2.41 by 6eb421d ("feat: support JPA annotation mapping for object model", #14626, TECH-1517), which swapped HibernateTransactionManager for JpaTransactionManager and dropped its setDataSource call. Affects 2.41, 2.42, 2.43 and master.

Analysis: https://dhis2.atlassian.net/browse/DHIS2-22067

@teleivo
teleivo marked this pull request as ready for review September 8, 2026 11:46
JpaTransactionManager was created without a DataSource, so Spring never
registered a ConnectionHolder under the DataSource key. Every
@transactional method mixing Hibernate and a plain JdbcTemplate took a
second connection from the same pool which was not enlisted in the
transaction: its statements commit immediately and a rollback does not
cover them.

This is why the org unit merge can destroy data. Its JDBC deletes of
datavalue and dataapproval commit as they run, so a later failure rolls
back the Hibernate work while the deleted rows stay gone.

Introduced in 2.41 by 6eb421d (#14626,
TECH-1517), which swapped HibernateTransactionManager for
JpaTransactionManager and dropped its setDataSource call.
@sonarqubecloud

sonarqubecloud Bot commented Sep 8, 2026

Copy link
Copy Markdown

@teleivo
teleivo merged commit b5ce871 into master Sep 8, 2026
26 of 27 checks passed
@teleivo
teleivo deleted the DHIS2-22067 branch September 8, 2026 13:07
teleivo added a commit that referenced this pull request Sep 9, 2026
) (#25072)

JpaTransactionManager was created without a DataSource, so Spring never
registered a ConnectionHolder under the DataSource key. Every
@transactional method mixing Hibernate and a plain JdbcTemplate took a
second connection from the same pool which was not enlisted in the
transaction: its statements commit immediately and a rollback does not
cover them.

This is why the org unit merge can destroy data. Its JDBC deletes of
datavalue and dataapproval commit as they run, so a later failure rolls
back the Hibernate work while the deleted rows stay gone.

Introduced in 2.41 by 6eb421d (#14626,
TECH-1517), which swapped HibernateTransactionManager for
JpaTransactionManager and dropped its setDataSource call.
teleivo added a commit that referenced this pull request Sep 9, 2026
) (#25071)

JpaTransactionManager was created without a DataSource, so Spring never
registered a ConnectionHolder under the DataSource key. Every
@transactional method mixing Hibernate and a plain JdbcTemplate took a
second connection from the same pool which was not enlisted in the
transaction: its statements commit immediately and a rollback does not
cover them.

This is why the org unit merge can destroy data. Its JDBC deletes of
datavalue and dataapproval commit as they run, so a later failure rolls
back the Hibernate work while the deleted rows stay gone.

Introduced in 2.41 by 6eb421d (#14626,
TECH-1517), which swapped HibernateTransactionManager for
JpaTransactionManager and dropped its setDataSource call.
teleivo added a commit that referenced this pull request Sep 9, 2026
) (#25070)

JpaTransactionManager was created without a DataSource, so Spring never
registered a ConnectionHolder under the DataSource key. Every
@transactional method mixing Hibernate and a plain JdbcTemplate took a
second connection from the same pool which was not enlisted in the
transaction: its statements commit immediately and a rollback does not
cover them.

This is why the org unit merge can destroy data. Its JDBC deletes of
datavalue and dataapproval commit as they run, so a later failure rolls
back the Hibernate work while the deleted rows stay gone.

Introduced in 2.41 by 6eb421d (#14626,
TECH-1517), which swapped HibernateTransactionManager for
JpaTransactionManager and dropped its setDataSource call.
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