Skip to content

Commit 5452144

Browse files
committed
HibernateJpaDialect only resets Connection read-only status if actually necessary (avoiding side effects)
Issue: SPR-8959 Issue: SPR-12118
1 parent 8c4388d commit 5452144

File tree

1 file changed

+22
-18
lines changed

1 file changed

+22
-18
lines changed

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

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -137,12 +137,15 @@ public Object beginTransaction(EntityManager entityManager, TransactionDefinitio
137137
session.getTransaction().setTimeout(definition.getTimeout());
138138
}
139139

140-
Integer previousIsolationLevel = null;
141140
boolean isolationLevelNeeded = (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT);
141+
Integer previousIsolationLevel = null;
142+
boolean resetConnection = false;
143+
142144
if (isolationLevelNeeded || definition.isReadOnly()) {
143145
if (this.prepareConnection) {
144146
Connection con = HibernateConnectionHandle.doGetConnection(session);
145147
previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
148+
resetConnection = true;
146149
}
147150
else if (isolationLevelNeeded) {
148151
throw new InvalidIsolationLevelException(getClass().getSimpleName() +
@@ -156,36 +159,37 @@ else if (isolationLevelNeeded) {
156159
entityManager.getTransaction().begin();
157160

158161
// Adapt flush mode and store previous isolation level, if any.
159-
return doPrepareTransaction(session, definition.isReadOnly(), previousIsolationLevel);
162+
FlushMode previousFlushMode = prepareFlushMode(session, definition.isReadOnly());
163+
return new SessionTransactionData(session, previousFlushMode, resetConnection, previousIsolationLevel);
160164
}
161165

162166
@Override
163167
public Object prepareTransaction(EntityManager entityManager, boolean readOnly, String name)
164168
throws PersistenceException {
165169

166-
return doPrepareTransaction(getSession(entityManager), readOnly, null);
170+
Session session = getSession(entityManager);
171+
FlushMode previousFlushMode = prepareFlushMode(session, readOnly);
172+
return new SessionTransactionData(session, previousFlushMode, false, null);
167173
}
168174

169-
protected Object doPrepareTransaction(Session session, boolean readOnly, Integer previousIsolationLevel)
170-
throws PersistenceException {
171-
175+
protected FlushMode prepareFlushMode(Session session, boolean readOnly) throws PersistenceException {
172176
FlushMode flushMode = session.getFlushMode();
173-
FlushMode previousFlushMode = null;
174177
if (readOnly) {
175178
// We should suppress flushing for a read-only transaction.
176-
session.setFlushMode(FlushMode.MANUAL);
177-
previousFlushMode = flushMode;
179+
if (!flushMode.equals(FlushMode.MANUAL)) {
180+
session.setFlushMode(FlushMode.MANUAL);
181+
return flushMode;
182+
}
178183
}
179184
else {
180185
// We need AUTO or COMMIT for a non-read-only transaction.
181186
if (flushMode.lessThan(FlushMode.COMMIT)) {
182187
session.setFlushMode(FlushMode.AUTO);
183-
previousFlushMode = flushMode;
188+
return flushMode;
184189
}
185190
}
186-
187-
boolean resetConnection = (previousIsolationLevel != null || readOnly);
188-
return new SessionTransactionData(session, previousFlushMode, resetConnection, previousIsolationLevel);
191+
// No FlushMode change needed...
192+
return null;
189193
}
190194

191195
@Override
@@ -299,8 +303,8 @@ protected DataAccessException convertHibernateAccessException(HibernateException
299303
return new JpaSystemException(ex);
300304
}
301305

302-
protected Session getSession(EntityManager em) {
303-
return em.unwrap(Session.class);
306+
protected Session getSession(EntityManager entityManager) {
307+
return entityManager.unwrap(Session.class);
304308
}
305309

306310

@@ -310,23 +314,23 @@ private static class SessionTransactionData {
310314

311315
private final FlushMode previousFlushMode;
312316

313-
private final boolean connectionReset;
317+
private final boolean resetConnection;
314318

315319
private final Integer previousIsolationLevel;
316320

317321
public SessionTransactionData(
318322
Session session, FlushMode previousFlushMode, boolean resetConnection, Integer previousIsolationLevel) {
319323
this.session = session;
320324
this.previousFlushMode = previousFlushMode;
321-
this.connectionReset = resetConnection;
325+
this.resetConnection = resetConnection;
322326
this.previousIsolationLevel = previousIsolationLevel;
323327
}
324328

325329
public void resetSessionState() {
326330
if (this.previousFlushMode != null) {
327331
this.session.setFlushMode(this.previousFlushMode);
328332
}
329-
if (this.connectionReset && this.session.isConnected()) {
333+
if (this.resetConnection && this.session.isConnected()) {
330334
Connection con = HibernateConnectionHandle.doGetConnection(this.session);
331335
DataSourceUtils.resetConnectionAfterTransaction(con, this.previousIsolationLevel);
332336
}

0 commit comments

Comments
 (0)