HibernateJpaDialect only resets Connection read-only status if actually necessary (avoiding side effects)
Issue: SPR-8959 Issue: SPR-12118
This commit is contained in:
parent
8c4388dd6e
commit
5452144dab
|
@ -137,12 +137,15 @@ public class HibernateJpaDialect extends DefaultJpaDialect {
|
||||||
session.getTransaction().setTimeout(definition.getTimeout());
|
session.getTransaction().setTimeout(definition.getTimeout());
|
||||||
}
|
}
|
||||||
|
|
||||||
Integer previousIsolationLevel = null;
|
|
||||||
boolean isolationLevelNeeded = (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT);
|
boolean isolationLevelNeeded = (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT);
|
||||||
|
Integer previousIsolationLevel = null;
|
||||||
|
boolean resetConnection = false;
|
||||||
|
|
||||||
if (isolationLevelNeeded || definition.isReadOnly()) {
|
if (isolationLevelNeeded || definition.isReadOnly()) {
|
||||||
if (this.prepareConnection) {
|
if (this.prepareConnection) {
|
||||||
Connection con = HibernateConnectionHandle.doGetConnection(session);
|
Connection con = HibernateConnectionHandle.doGetConnection(session);
|
||||||
previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
|
previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
|
||||||
|
resetConnection = true;
|
||||||
}
|
}
|
||||||
else if (isolationLevelNeeded) {
|
else if (isolationLevelNeeded) {
|
||||||
throw new InvalidIsolationLevelException(getClass().getSimpleName() +
|
throw new InvalidIsolationLevelException(getClass().getSimpleName() +
|
||||||
|
@ -156,36 +159,37 @@ public class HibernateJpaDialect extends DefaultJpaDialect {
|
||||||
entityManager.getTransaction().begin();
|
entityManager.getTransaction().begin();
|
||||||
|
|
||||||
// Adapt flush mode and store previous isolation level, if any.
|
// Adapt flush mode and store previous isolation level, if any.
|
||||||
return doPrepareTransaction(session, definition.isReadOnly(), previousIsolationLevel);
|
FlushMode previousFlushMode = prepareFlushMode(session, definition.isReadOnly());
|
||||||
|
return new SessionTransactionData(session, previousFlushMode, resetConnection, previousIsolationLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object prepareTransaction(EntityManager entityManager, boolean readOnly, String name)
|
public Object prepareTransaction(EntityManager entityManager, boolean readOnly, String name)
|
||||||
throws PersistenceException {
|
throws PersistenceException {
|
||||||
|
|
||||||
return doPrepareTransaction(getSession(entityManager), readOnly, null);
|
Session session = getSession(entityManager);
|
||||||
|
FlushMode previousFlushMode = prepareFlushMode(session, readOnly);
|
||||||
|
return new SessionTransactionData(session, previousFlushMode, false, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Object doPrepareTransaction(Session session, boolean readOnly, Integer previousIsolationLevel)
|
protected FlushMode prepareFlushMode(Session session, boolean readOnly) throws PersistenceException {
|
||||||
throws PersistenceException {
|
|
||||||
|
|
||||||
FlushMode flushMode = session.getFlushMode();
|
FlushMode flushMode = session.getFlushMode();
|
||||||
FlushMode previousFlushMode = null;
|
|
||||||
if (readOnly) {
|
if (readOnly) {
|
||||||
// We should suppress flushing for a read-only transaction.
|
// We should suppress flushing for a read-only transaction.
|
||||||
session.setFlushMode(FlushMode.MANUAL);
|
if (!flushMode.equals(FlushMode.MANUAL)) {
|
||||||
previousFlushMode = flushMode;
|
session.setFlushMode(FlushMode.MANUAL);
|
||||||
|
return flushMode;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// We need AUTO or COMMIT for a non-read-only transaction.
|
// We need AUTO or COMMIT for a non-read-only transaction.
|
||||||
if (flushMode.lessThan(FlushMode.COMMIT)) {
|
if (flushMode.lessThan(FlushMode.COMMIT)) {
|
||||||
session.setFlushMode(FlushMode.AUTO);
|
session.setFlushMode(FlushMode.AUTO);
|
||||||
previousFlushMode = flushMode;
|
return flushMode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// No FlushMode change needed...
|
||||||
boolean resetConnection = (previousIsolationLevel != null || readOnly);
|
return null;
|
||||||
return new SessionTransactionData(session, previousFlushMode, resetConnection, previousIsolationLevel);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -299,8 +303,8 @@ public class HibernateJpaDialect extends DefaultJpaDialect {
|
||||||
return new JpaSystemException(ex);
|
return new JpaSystemException(ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Session getSession(EntityManager em) {
|
protected Session getSession(EntityManager entityManager) {
|
||||||
return em.unwrap(Session.class);
|
return entityManager.unwrap(Session.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -310,7 +314,7 @@ public class HibernateJpaDialect extends DefaultJpaDialect {
|
||||||
|
|
||||||
private final FlushMode previousFlushMode;
|
private final FlushMode previousFlushMode;
|
||||||
|
|
||||||
private final boolean connectionReset;
|
private final boolean resetConnection;
|
||||||
|
|
||||||
private final Integer previousIsolationLevel;
|
private final Integer previousIsolationLevel;
|
||||||
|
|
||||||
|
@ -318,7 +322,7 @@ public class HibernateJpaDialect extends DefaultJpaDialect {
|
||||||
Session session, FlushMode previousFlushMode, boolean resetConnection, Integer previousIsolationLevel) {
|
Session session, FlushMode previousFlushMode, boolean resetConnection, Integer previousIsolationLevel) {
|
||||||
this.session = session;
|
this.session = session;
|
||||||
this.previousFlushMode = previousFlushMode;
|
this.previousFlushMode = previousFlushMode;
|
||||||
this.connectionReset = resetConnection;
|
this.resetConnection = resetConnection;
|
||||||
this.previousIsolationLevel = previousIsolationLevel;
|
this.previousIsolationLevel = previousIsolationLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -326,7 +330,7 @@ public class HibernateJpaDialect extends DefaultJpaDialect {
|
||||||
if (this.previousFlushMode != null) {
|
if (this.previousFlushMode != null) {
|
||||||
this.session.setFlushMode(this.previousFlushMode);
|
this.session.setFlushMode(this.previousFlushMode);
|
||||||
}
|
}
|
||||||
if (this.connectionReset && this.session.isConnected()) {
|
if (this.resetConnection && this.session.isConnected()) {
|
||||||
Connection con = HibernateConnectionHandle.doGetConnection(this.session);
|
Connection con = HibernateConnectionHandle.doGetConnection(this.session);
|
||||||
DataSourceUtils.resetConnectionAfterTransaction(con, this.previousIsolationLevel);
|
DataSourceUtils.resetConnectionAfterTransaction(con, this.previousIsolationLevel);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue