Merge branch '7.0.x'

# Conflicts:
#	framework-platform/framework-platform.gradle
This commit is contained in:
Juergen Hoeller
2026-09-14 16:22:05 +02:00
6 changed files with 102 additions and 14 deletions
+8 -8
View File
@@ -9,14 +9,14 @@ javaPlatform {
dependencies {
api(platform("com.fasterxml.jackson:jackson-bom:2.21.5"))
api(platform("io.micrometer:micrometer-bom:1.18.0-M1"))
api(platform("io.netty:netty-bom:4.2.17.Final"))
api(platform("io.netty:netty-bom:4.2.18.Final"))
api(platform("io.projectreactor:reactor-bom:2026.0.0-SNAPSHOT"))
api(platform("io.rsocket:rsocket-bom:1.1.5"))
api(platform("org.apache.groovy:groovy-bom:5.1.1"))
api(platform("org.apache.logging.log4j:log4j-bom:2.26.1"))
api(platform("org.assertj:assertj-bom:3.27.7"))
api(platform("org.eclipse.jetty:jetty-bom:12.1.12"))
api(platform("org.eclipse.jetty.ee11:jetty-ee11-bom:12.1.12"))
api(platform("org.eclipse.jetty:jetty-bom:12.1.13"))
api(platform("org.eclipse.jetty.ee11:jetty-ee11-bom:12.1.13"))
api(platform("org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.11.0"))
api(platform("org.jetbrains.kotlinx:kotlinx-serialization-bom:1.11.0"))
api(platform("org.junit:junit-bom:6.1.2"))
@@ -31,7 +31,7 @@ dependencies {
api("com.google.code.findbugs:findbugs:3.0.1")
api("com.google.code.findbugs:jsr305:3.0.2")
api("com.google.code.gson:gson:2.14.0")
api("com.google.protobuf:protobuf-java-util:4.35.1")
api("com.google.protobuf:protobuf-java-util:4.36.1")
api("com.h2database:h2:2.4.240")
api("com.jayway.jsonpath:json-path:2.10.0")
api("com.networknt:json-schema-validator:1.5.3")
@@ -96,10 +96,10 @@ dependencies {
api("org.apache.httpcomponents.client5:httpclient5:5.6")
api("org.apache.httpcomponents.core5:httpcore5-reactive:5.4.2")
api("org.apache.poi:poi-ooxml:5.5.1")
api("org.apache.tomcat.embed:tomcat-embed-core:11.0.24")
api("org.apache.tomcat.embed:tomcat-embed-websocket:11.0.24")
api("org.apache.tomcat:tomcat-util:11.0.24")
api("org.apache.tomcat:tomcat-websocket:11.0.24")
api("org.apache.tomcat.embed:tomcat-embed-core:11.0.25")
api("org.apache.tomcat.embed:tomcat-embed-websocket:11.0.25")
api("org.apache.tomcat:tomcat-util:11.0.25")
api("org.apache.tomcat:tomcat-websocket:11.0.25")
api("org.aspectj:aspectjrt:1.9.25")
api("org.aspectj:aspectjtools:1.9.25")
api("org.aspectj:aspectjweaver:1.9.25")
@@ -54,6 +54,13 @@ public class EntityManagerHolder extends ResourceHolderSupport {
this.entityAgent = entityAgent;
}
protected EntityManagerHolder(EntityManagerHolder original) {
this.entityManager = original.entityManager;
this.entityAgent = original.entityAgent;
this.transactionActive = original.transactionActive;
this.savepointManager = original.savepointManager;
}
void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
@@ -44,6 +44,7 @@ import org.springframework.jdbc.datasource.DataSourceUtils;
import org.springframework.jdbc.datasource.JdbcTransactionObjectSupport;
import org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy;
import org.springframework.orm.jpa.EntityManagerFactoryUtils;
import org.springframework.orm.jpa.EntityManagerHolder;
import org.springframework.transaction.CannotCreateTransactionException;
import org.springframework.transaction.IllegalTransactionStateException;
import org.springframework.transaction.InvalidIsolationLevelException;
@@ -391,9 +392,17 @@ public class HibernateTransactionManager extends AbstractPlatformTransactionMana
txObject.setSavepointAllowed(isNestedTransactionAllowed());
SessionFactory sessionFactory = obtainSessionFactory();
SessionHolder sessionHolder =
(SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);
if (sessionHolder != null) {
Object resource = TransactionSynchronizationManager.getResource(sessionFactory);
if (resource instanceof EntityManagerHolder emHolder) {
SessionHolder sessionHolder;
if (emHolder instanceof SessionHolder originalSessionHolder) {
sessionHolder = originalSessionHolder;
}
else {
sessionHolder = new SessionHolder(emHolder);
TransactionSynchronizationManager.unbindResource(sessionFactory);
TransactionSynchronizationManager.bindResource(sessionFactory, sessionHolder);
}
if (logger.isDebugEnabled()) {
logger.debug("Found thread-bound Session [" + sessionHolder.getSession() + "] for Hibernate transaction");
}
@@ -16,6 +16,7 @@
package org.springframework.orm.jpa.hibernate;
import jakarta.persistence.EntityManager;
import org.hibernate.FlushMode;
import org.hibernate.Session;
import org.hibernate.StatelessSession;
@@ -49,10 +50,14 @@ public class SessionHolder extends EntityManagerHolder {
}
SessionHolder(StatelessSession session) {
super(null);
super((EntityManager) null);
setStatelessSession(session);
}
SessionHolder(EntityManagerHolder emHolder) {
super(emHolder);
}
void setSession(Session session) {
this.entityManager = session;
@@ -187,7 +187,16 @@ public class SpringSessionContext implements CurrentSessionContext {
if (value instanceof StatelessSession statelessSession) {
return statelessSession;
}
if (value instanceof SessionHolder sessionHolder) {
else if (value instanceof EntityManagerHolder emHolder) {
SessionHolder sessionHolder;
if (emHolder instanceof SessionHolder originalSessionHolder) {
sessionHolder = originalSessionHolder;
}
else {
sessionHolder = new SessionHolder(emHolder);
TransactionSynchronizationManager.unbindResource(sessionFactory);
TransactionSynchronizationManager.bindResource(sessionFactory, sessionHolder);
}
if (sessionHolder.hasStatelessSession()) {
return sessionHolder.getStatelessSession();
}
@@ -216,7 +225,7 @@ public class SpringSessionContext implements CurrentSessionContext {
return session;
}
throw new HibernateException("Could not obtain transaction-synchronized Session for current thread");
throw new HibernateException("Could not obtain transaction-synchronized StatelessSession for current thread");
}
private static void bindSessionHolder(SessionFactory sessionFactory, SessionHolder holder) {
@@ -32,7 +32,10 @@ import org.springframework.context.ApplicationContext;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.orm.jpa.AbstractContainerEntityManagerFactoryIntegrationTests;
import org.springframework.orm.jpa.EntityManagerFactoryInfo;
import org.springframework.orm.jpa.EntityManagerHolder;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.domain.Person;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.transaction.support.TransactionTemplate;
import static org.assertj.core.api.Assertions.assertThat;
@@ -150,6 +153,61 @@ class HibernateNativeEntityManagerFactoryIntegrationTests extends AbstractContai
});
}
@Test
void withJpaTransactionManager() {
String firstName = "Tony";
insertPerson(firstName);
Query<Person> q = statelessSession.createQuery("select p from Person as p", Person.class);
assertThat(q.getResultList()).hasSize(1);
assertThat(q.getResultList().get(0).getFirstName()).isEqualTo(firstName);
endTransaction();
JpaTransactionManager dstm = new JpaTransactionManager(sessionFactory);
new TransactionTemplate(dstm).execute(status -> {
insertPerson(firstName);
Query<Person> q2 = statelessSession.createQuery("select p from Person as p", Person.class);
assertThat(q2.getResultList()).hasSize(1);
assertThat(q2.getResultList().get(0).getFirstName()).isEqualTo(firstName);
Query<Person> q3 = sharedSession.createQuery("select p from Person as p", Person.class);
assertThat(q3.getResultList()).hasSize(1);
assertThat(q3.getResultList().get(0).getFirstName()).isEqualTo(firstName);
status.setRollbackOnly();
return null;
});
}
@Test
void withPreBoundEntityManager() {
String firstName = "Tony";
insertPerson(firstName);
Query<Person> q = statelessSession.createQuery("select p from Person as p", Person.class);
assertThat(q.getResultList()).hasSize(1);
assertThat(q.getResultList().get(0).getFirstName()).isEqualTo(firstName);
endTransaction();
Session session = sessionFactory.openSession();
TransactionSynchronizationManager.bindResource(sessionFactory, new EntityManagerHolder(session));
startNewTransaction();
insertPerson(firstName);
Query<Person> q2 = statelessSession.createQuery("select p from Person as p", Person.class);
assertThat(q2.getResultList()).hasSize(1);
assertThat(q2.getResultList().get(0).getFirstName()).isEqualTo(firstName);
Query<Person> q3 = sharedSession.createQuery("select p from Person as p", Person.class);
assertThat(q3.getResultList()).hasSize(1);
assertThat(q3.getResultList().get(0).getFirstName()).isEqualTo(firstName);
endTransaction();
session.close();
TransactionSynchronizationManager.unbindResource(sessionFactory);
}
@Test // SPR-16956
void readOnly() {
assertThat(sessionFactory.getCurrentSession().getHibernateFlushMode()).isSameAs(FlushMode.AUTO);