Skip to content

Commit 711eb99

Browse files
committed
HibernateJpaVendorAdapter and LocalSessionFactoryBuilder enforce Hibernate 5.2's connection handling mode DELAYED_ACQUISITION_AND_HOLD
Issue: SPR-14393
1 parent 5e08598 commit 711eb99

File tree

4 files changed

+38
-15
lines changed

4 files changed

+38
-15
lines changed

spring-orm-hibernate5/src/main/java/org/springframework/orm/hibernate5/HibernateTransactionManager.java

-2
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,6 @@ public void setPrepareConnection(boolean prepareConnection) {
235235
* <p>Default is "false". Turning this flag on enforces over-commit holdability on the
236236
* underlying JDBC Connection (if {@link #prepareConnection "prepareConnection"} is on)
237237
* and skips the disconnect-on-completion step.
238-
* @since 4.2
239238
* @see Connection#setHoldability
240239
* @see ResultSet#HOLD_CURSORS_OVER_COMMIT
241240
* @see #disconnectOnCompletion(Session)
@@ -689,7 +688,6 @@ protected void doCleanupAfterCompletion(Object transaction) {
689688
* <p>The default implementation simply calls {@link Session#disconnect()}.
690689
* Subclasses may override this with a no-op or with fine-tuned disconnection logic.
691690
* @param session the Hibernate Session to disconnect
692-
* @since 4.2
693691
* @see Session#disconnect()
694692
*/
695693
protected void disconnectOnCompletion(Session session) {

spring-orm-hibernate5/src/main/java/org/springframework/orm/hibernate5/LocalSessionFactoryBuilder.java

+9
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,10 @@ public LocalSessionFactoryBuilder(DataSource dataSource, ResourceLoader resource
139139
if (dataSource != null) {
140140
getProperties().put(Environment.DATASOURCE, dataSource);
141141
}
142+
143+
// Hibernate 5.2: manually enforce connection release mode ON_CLOSE (the former default)
144+
getProperties().put("hibernate.connection.handling_mode", "DELAYED_ACQUISITION_AND_HOLD");
145+
142146
getProperties().put(AvailableSettings.CLASSLOADERS, Collections.singleton(resourceLoader.getClassLoader()));
143147
this.resourcePatternResolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader);
144148
}
@@ -157,6 +161,7 @@ public LocalSessionFactoryBuilder(DataSource dataSource, ResourceLoader resource
157161
*/
158162
public LocalSessionFactoryBuilder setJtaTransactionManager(Object jtaTransactionManager) {
159163
Assert.notNull(jtaTransactionManager, "Transaction manager reference must not be null");
164+
160165
if (jtaTransactionManager instanceof JtaTransactionManager) {
161166
boolean webspherePresent = ClassUtils.isPresent("com.ibm.wsspi.uow.UOWManager", getClass().getClassLoader());
162167
if (webspherePresent) {
@@ -182,6 +187,10 @@ else if (jtaTransactionManager instanceof TransactionManager) {
182187
throw new IllegalArgumentException(
183188
"Unknown transaction manager type: " + jtaTransactionManager.getClass().getName());
184189
}
190+
191+
// Hibernate 5.2: manually enforce connection release mode AFTER_STATEMENT (the JTA default)
192+
getProperties().remove("hibernate.connection.handling_mode", "DELAYED_ACQUISITION_AND_RELEASE_AFTER_STATEMENT");
193+
185194
return this;
186195
}
187196

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

+3-13
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ public class HibernateJpaDialect extends DefaultJpaDialect {
126126
}
127127

128128

129-
private boolean prepareConnection = (HibernateConnectionHandle.sessionConnectionMethod == null);
129+
boolean prepareConnection = (HibernateConnectionHandle.sessionConnectionMethod == null);
130130

131131

132132
/**
@@ -362,25 +362,15 @@ public void resetSessionState() {
362362
}
363363
if (this.preparedCon != null && this.session.isConnected()) {
364364
Connection conToReset = HibernateConnectionHandle.doGetConnection(this.session);
365-
if (!isEquivalentConnection(conToReset)) {
365+
if (conToReset != this.preparedCon) {
366366
LogFactory.getLog(HibernateJpaDialect.class).warn(
367-
"JDBC Connection to reset not equivalent to originally prepared Connection - please " +
367+
"JDBC Connection to reset not identical to originally prepared Connection - please " +
368368
"make sure to use connection release mode ON_CLOSE (the default) and to run against " +
369369
"Hibernate 4.2+ (or switch HibernateJpaDialect's prepareConnection flag to false");
370370
}
371371
DataSourceUtils.resetConnectionAfterTransaction(conToReset, this.previousIsolationLevel);
372372
}
373373
}
374-
375-
private boolean isEquivalentConnection(Connection con) {
376-
try {
377-
return (con.equals(this.preparedCon) ||
378-
con.unwrap(Connection.class).equals(this.preparedCon.unwrap(Connection.class)));
379-
}
380-
catch (Throwable ex) {
381-
return false;
382-
}
383-
}
384374
}
385375

386376

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

+26
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,27 @@ public HibernateJpaVendorAdapter() {
101101
}
102102

103103

104+
/**
105+
* Set whether to prepare the underlying JDBC Connection of a transactional
106+
* Hibernate Session, that is, whether to apply a transaction-specific
107+
* isolation level and/or the transaction's read-only flag to the underlying
108+
* JDBC Connection.
109+
* <p>See {@link HibernateJpaDialect#setPrepareConnection(boolean)} for details.
110+
* This is just a convenience flag passed through to {@code HibernateJpaDialect}.
111+
* <p>On Hibernate 5.2, this flag remains {@code true} by default like against
112+
* previous Hibernate versions. The vendor adapter manually enforces Hibernate's
113+
* new connection handling mode {@code DELAYED_ACQUISITION_AND_HOLD} in that case
114+
* unless a user-specified connection handling mode property indicates otherwise;
115+
* switch this flag to {@code false} to avoid that interference.
116+
* @since 4.3.1
117+
* @see #getJpaPropertyMap()
118+
* @see HibernateJpaDialect#beginTransaction
119+
*/
120+
public void setPrepareConnection(boolean prepareConnection) {
121+
this.jpaDialect.setPrepareConnection(prepareConnection);
122+
}
123+
124+
104125
@Override
105126
public PersistenceProvider getPersistenceProvider() {
106127
return this.persistenceProvider;
@@ -132,6 +153,11 @@ else if (getDatabase() != null) {
132153
jpaProperties.put(Environment.SHOW_SQL, "true");
133154
}
134155

156+
if (this.jpaDialect.prepareConnection) {
157+
// Hibernate 5.2: manually enforce connection release mode ON_CLOSE (the former default)
158+
jpaProperties.put("hibernate.connection.handling_mode", "DELAYED_ACQUISITION_AND_HOLD");
159+
}
160+
135161
return jpaProperties;
136162
}
137163

0 commit comments

Comments
 (0)