Polish contribution

See gh-37356
This commit is contained in:
Sam Brannen
2026-10-02 15:49:37 +02:00
parent 912b0bce9d
commit db4f57a54f
4 changed files with 85 additions and 20 deletions
@@ -387,15 +387,11 @@ public class JpaTransactionManager extends AbstractPlatformTransactionManager
JpaTransactionObject txObject = (JpaTransactionObject) transaction;
if (txObject.hasConnectionHolder() && !txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
throw new IllegalTransactionStateException(
"Pre-bound JDBC Connection found! JpaTransactionManager does not support " +
"running within another transaction manager that exposes a JDBC Connection " +
"for the same DataSource (for example, a JpaTransactionManager or " +
"HibernateTransactionManager for a different persistence unit) if told to " +
"manage the DataSource itself. Alternatively, a JDBC Connection may have been " +
"left bound to the current thread. It is recommended to use a single " +
"JpaTransactionManager for all transactions on a single DataSource, " +
"no matter whether JPA or JDBC access.");
throw new IllegalTransactionStateException("""
Pre-bound JDBC Connection found! JpaTransactionManager does not support running within \
another transaction manager that exposes a JDBC Connection for the same DataSource \
(or after a leaked Connection binding) if told to manage the DataSource itself. \
Use a single JpaTransactionManager for all transactions on a single DataSource.""");
}
try {
@@ -443,15 +443,11 @@ public class HibernateTransactionManager extends AbstractPlatformTransactionMana
HibernateTransactionObject txObject = (HibernateTransactionObject) transaction;
if (txObject.hasConnectionHolder() && !txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
throw new IllegalTransactionStateException(
"Pre-bound JDBC Connection found! HibernateTransactionManager does not support " +
"running within another transaction manager that exposes a JDBC Connection " +
"for the same DataSource (for example, a HibernateTransactionManager or " +
"JpaTransactionManager for a different SessionFactory) if told to manage " +
"the DataSource itself. Alternatively, a JDBC Connection may have been " +
"left bound to the current thread. It is recommended to use a single " +
"HibernateTransactionManager for all transactions on a single DataSource, " +
"no matter whether Hibernate or JDBC access.");
throw new IllegalTransactionStateException("""
Pre-bound JDBC Connection found! HibernateTransactionManager does not support running within \
another transaction manager that exposes a JDBC Connection for the same DataSource \
(or after a leaked Connection binding) if told to manage the DataSource itself. \
Use a single HibernateTransactionManager for all transactions on a single DataSource.""");
}
SessionImplementor session = null;
@@ -50,6 +50,7 @@ import static org.mockito.Mockito.verify;
/**
* Unit tests for {@link JpaTransactionManager}.
*
* @author Costin Leau
* @author Juergen Hoeller
* @author Phillip Webb
@@ -619,7 +620,7 @@ class JpaTransactionManagerTests {
verify(manager).close();
}
@Test // gh-14130
@Test // gh-37356
void transactionWithinOtherTransactionManagerForSameDataSource() {
DataSource dataSource = mock();
Connection connection = mock();
@@ -641,9 +642,10 @@ class JpaTransactionManagerTests {
otherTm.setJpaDialect(jpaDialect);
tm.setDataSource(dataSource);
tm.setJpaDialect(jpaDialect);
TransactionTemplate otherTt = new TransactionTemplate(otherTm);
assertThatExceptionOfType(IllegalTransactionStateException.class)
.isThrownBy(() -> new TransactionTemplate(otherTm).executeWithoutResult(status ->
.isThrownBy(() -> otherTt.executeWithoutResult(status ->
tt.executeWithoutResult(innerStatus -> {})))
.withMessageStartingWith("Pre-bound JDBC Connection found!")
.withMessageContaining("another transaction manager")
@@ -0,0 +1,71 @@
/*
* Copyright 2002-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.orm.jpa.hibernate;
import java.sql.Connection;
import javax.sql.DataSource;
import org.hibernate.SessionFactory;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.springframework.jdbc.datasource.ConnectionHolder;
import org.springframework.transaction.IllegalTransactionStateException;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.transaction.support.TransactionTemplate;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.mockito.Mockito.mock;
/**
* Unit tests for {@link HibernateTransactionManager}.
*
* @author Sam Brannen
* @since 7.1
*/
class HibernateTransactionManagerTests {
private final DataSource dataSource = mock();
@AfterEach
void unbindDataSource() {
if (TransactionSynchronizationManager.hasResource(this.dataSource)) {
TransactionSynchronizationManager.unbindResource(this.dataSource);
}
}
@Test // gh-37356
void transactionWithinOtherTransactionManagerForSameDataSource() {
HibernateTransactionManager tm = new HibernateTransactionManager(mock(SessionFactory.class));
tm.setAutodetectDataSource(false);
tm.setDataSource(this.dataSource);
TransactionTemplate transactionTemplate = new TransactionTemplate(tm);
// Simulate a JDBC Connection exposed by another transaction manager for the same DataSource.
TransactionSynchronizationManager.bindResource(this.dataSource, new ConnectionHolder(mock(Connection.class)));
assertThatExceptionOfType(IllegalTransactionStateException.class)
.isThrownBy(() -> transactionTemplate.executeWithoutResult(status -> {}))
.withMessageStartingWith("Pre-bound JDBC Connection found!")
.withMessageContaining("another transaction manager")
.withMessageNotContaining("DataSourceTransactionManager");
}
}