Skip to content

Commit 184455d

Browse files
committed
Upgraded to Hibernate 4.2.0
HibernateJpaDialect's HibernateConnectionHandle does not call close() for Hibernate 4.x anymore, since on 4.2, the exposed Connection handle isn't a "borrowed connection" wrapper but rather the actual underlying Connection - with a close() call immediately returning the Connection to the pool and making the local handle invalid for further use within the transaction. Also using JPA 2.0's EntityManager unwrap method now for retrieving the underlying Hibernate Session. Issue: SPR-10395
1 parent 6d71056 commit 184455d

File tree

2 files changed

+24
-25
lines changed

2 files changed

+24
-25
lines changed

build.gradle

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -502,8 +502,8 @@ project("spring-orm-hibernate4") {
502502
dependencies {
503503
provided(project(":spring-tx"))
504504
provided(project(":spring-jdbc"))
505-
optional("org.hibernate:hibernate-core:4.1.9.Final")
506-
optional("org.hibernate:hibernate-entitymanager:4.1.9.Final")
505+
optional("org.hibernate:hibernate-core:4.2.0.Final")
506+
optional("org.hibernate:hibernate-entitymanager:4.2.0.Final")
507507
optional(project(":spring-web"))
508508
optional("javax.servlet:javax.servlet-api:3.0.1")
509509
}
@@ -751,7 +751,7 @@ configure(rootProject) {
751751
testCompile(project(":spring-web"))
752752
testCompile(project(":spring-webmvc-portlet"))
753753
testCompile(project(":spring-orm"))
754-
testCompile("org.hibernate:hibernate-core:4.1.9.Final")
754+
testCompile("org.hibernate:hibernate-core:4.2.0.Final")
755755
testCompile("javax.servlet:javax.servlet-api:3.0.1")
756756
testCompile("javax.portlet:portlet-api:2.0")
757757
testCompile("javax.inject:javax.inject:1")

spring-orm/src/main/java/org/springframework/orm/jpa/vendor/HibernateJpaDialect.java

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2012 the original author or authors.
2+
* Copyright 2002-2013 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -25,7 +25,6 @@
2525
import org.hibernate.FlushMode;
2626
import org.hibernate.HibernateException;
2727
import org.hibernate.Session;
28-
import org.hibernate.ejb.HibernateEntityManager;
2928

3029
import org.springframework.dao.DataAccessException;
3130
import org.springframework.jdbc.datasource.ConnectionHandle;
@@ -35,6 +34,7 @@
3534
import org.springframework.orm.jpa.EntityManagerFactoryUtils;
3635
import org.springframework.transaction.TransactionDefinition;
3736
import org.springframework.transaction.TransactionException;
37+
import org.springframework.util.ClassUtils;
3838
import org.springframework.util.ReflectionUtils;
3939

4040
/**
@@ -106,19 +106,7 @@ public DataAccessException translateExceptionIfPossible(RuntimeException ex) {
106106
}
107107

108108
protected Session getSession(EntityManager em) {
109-
if (em instanceof HibernateEntityManager) {
110-
return ((HibernateEntityManager) em).getSession();
111-
}
112-
else {
113-
Object delegate = em.getDelegate();
114-
if (delegate instanceof Session) {
115-
return (Session) delegate;
116-
}
117-
else {
118-
throw new IllegalStateException(
119-
"Cannot obtain native Hibernate Session from given JPA EntityManager: " + em.getClass());
120-
}
121-
}
109+
return em.unwrap(Session.class);
122110
}
123111

124112

@@ -145,27 +133,38 @@ private static class HibernateConnectionHandle implements ConnectionHandle {
145133

146134
private final Session session;
147135

148-
private static volatile Method connectionMethod;
136+
// This will find a corresponding method on Hibernate 3.x but not on 4.x
137+
private static final Method sessionConnectionMethod =
138+
ClassUtils.getMethodIfAvailable(Session.class, "connection");
139+
140+
private static volatile Method connectionMethodToUse = sessionConnectionMethod;
149141

150142
public HibernateConnectionHandle(Session session) {
151143
this.session = session;
152144
}
153145

154146
public Connection getConnection() {
155147
try {
156-
if (connectionMethod == null) {
157-
// reflective lookup to bridge between Hibernate 3.x and 4.x
158-
connectionMethod = this.session.getClass().getMethod("connection");
148+
if (connectionMethodToUse == null) {
149+
// Reflective lookup trying to find SessionImpl's connection() on Hibernate 4.x
150+
connectionMethodToUse = this.session.getClass().getMethod("connection");
159151
}
160-
return (Connection) ReflectionUtils.invokeMethod(connectionMethod, this.session);
152+
return (Connection) ReflectionUtils.invokeMethod(connectionMethodToUse, this.session);
161153
}
162154
catch (NoSuchMethodException ex) {
163-
throw new IllegalStateException("Cannot find connection() method on Hibernate session", ex);
155+
throw new IllegalStateException("Cannot find connection() method on Hibernate Session", ex);
164156
}
165157
}
166158

167159
public void releaseConnection(Connection con) {
168-
JdbcUtils.closeConnection(con);
160+
if (sessionConnectionMethod != null) {
161+
// Need to explicitly call close() with Hibernate 3.x in order to allow
162+
// for eager release of the underlying physical Connection if necessary.
163+
// However, do not do this on Hibernate 4.2+ since it would return the
164+
// physical Connection to the pool right away, making it unusable for
165+
// further operations within the current transaction!
166+
JdbcUtils.closeConnection(con);
167+
}
169168
}
170169
}
171170

0 commit comments

Comments
 (0)