1
1
/*
2
- * Copyright 2002-2012 the original author or authors.
2
+ * Copyright 2002-2013 the original author or authors.
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
25
25
import org .hibernate .FlushMode ;
26
26
import org .hibernate .HibernateException ;
27
27
import org .hibernate .Session ;
28
- import org .hibernate .ejb .HibernateEntityManager ;
29
28
30
29
import org .springframework .dao .DataAccessException ;
31
30
import org .springframework .jdbc .datasource .ConnectionHandle ;
35
34
import org .springframework .orm .jpa .EntityManagerFactoryUtils ;
36
35
import org .springframework .transaction .TransactionDefinition ;
37
36
import org .springframework .transaction .TransactionException ;
37
+ import org .springframework .util .ClassUtils ;
38
38
import org .springframework .util .ReflectionUtils ;
39
39
40
40
/**
@@ -106,19 +106,7 @@ public DataAccessException translateExceptionIfPossible(RuntimeException ex) {
106
106
}
107
107
108
108
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 );
122
110
}
123
111
124
112
@@ -145,27 +133,38 @@ private static class HibernateConnectionHandle implements ConnectionHandle {
145
133
146
134
private final Session session ;
147
135
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 ;
149
141
150
142
public HibernateConnectionHandle (Session session ) {
151
143
this .session = session ;
152
144
}
153
145
154
146
public Connection getConnection () {
155
147
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" );
159
151
}
160
- return (Connection ) ReflectionUtils .invokeMethod (connectionMethod , this .session );
152
+ return (Connection ) ReflectionUtils .invokeMethod (connectionMethodToUse , this .session );
161
153
}
162
154
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 );
164
156
}
165
157
}
166
158
167
159
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
+ }
169
168
}
170
169
}
171
170
0 commit comments