结论:commit时会自动flush
commit后再进行flush会报错,如下
org.springframework.dao.InvalidDataAccessApiUsageException: no transaction is in progress; nested exception is javax.persistence.TransactionRequiredException: no transaction is in progress
接下来是源码详解
环境 hibernate5
TransactionImpl 类
@Override
public void commit() {
if ( !isActive( true ) ) {
// allow MARKED_ROLLBACK to propagate through to transactionDriverControl
// the boolean passed to isActive indicates whether MARKED_ROLLBACK should be
// considered active
//
// essentially here we have a transaction that is not active and
// has not been marked for rollback only
throw new IllegalStateException( "Transaction not successfully started" );
}
LOG.debug( "committing" );
try {
internalGetTransactionDriverControl().commit();
}
catch (RuntimeException e) {
throw exceptionConverter.convertCommitException( e );
}
}
代码没什么可说的直接看 internalGetTransactionDriverControl().commit();
JdbcResourceLocalTransactionCoordinatorImpl 类
@Override
public void commit() {
try {
if ( rollbackOnly ) {
log.debugf( "On commit, transaction was marked for roll-back only, rolling back" );
try {
rollback();
if ( jpaCompliance.isJpaTransactionComplianceEnabled() ) {
log.debugf( "Throwing RollbackException on roll-back of transaction marked rollback-only on commit" );
throw new RollbackException( "Transaction was marked for rollback-only" );
}
return;
}
catch (RollbackException e) {
throw e;
}
catch (RuntimeException e) {
log.debug( "Encountered failure rolling back failed commit", e );
throw e;
}
}
JdbcResourceLocalTransactionCoordinatorImpl.this.beforeCompletionCallback();
jdbcResourceTransaction.commit();
JdbcResourceLocalTransactionCoordinatorImpl.this.afterCompletionCallback( true );
}
catch (RollbackException e) {
throw e;
}
catch (RuntimeException e) {
try {
rollback();
}
catch (RuntimeException e2) {
log.debug( "Encountered failure rolling back failed commit", e2 );;
}
throw e;
}
}
private void beforeCompletionCallback() {
log.trace( "ResourceLocalTransactionCoordinatorImpl#beforeCompletionCallback" );
try {
transactionCoordinatorOwner.beforeTransactionCompletion();
synchronizationRegistry.notifySynchronizationsBeforeTransactionCompletion();
for ( TransactionObserver observer : observers() ) {
observer.beforeCompletion();
}
}
catch (RuntimeException e) {
if ( physicalTransactionDelegate != null ) {
// should never happen that the physicalTransactionDelegate is null, but to be safe
physicalTransactionDelegate.markRollbackOnly();
}
throw e;
}
}
JdbcCoordinatorImpl 类
@Override
public void beforeTransactionCompletion() {
owner.beforeTransactionCompletion();
}
SessionImpl 类
@Override
public void beforeTransactionCompletion() {
log.tracef( "SessionImpl#beforeTransactionCompletion()" );
flushBeforeTransactionCompletion();
actionQueue.beforeTransactionCompletion();
try {
getInterceptor().beforeTransactionCompletion( getTransactionIfAccessible() );
}
catch (Throwable t) {
log.exceptionInBeforeTransactionCompletionInterceptor( t );
}
super.beforeTransactionCompletion();
}
@Override
public void flushBeforeTransactionCompletion() {
final boolean doFlush = isTransactionFlushable()
&& getHibernateFlushMode() != FlushMode.MANUAL;
try {
if ( doFlush ) {
managedFlush();
}
}
catch (RuntimeException re) {
throw exceptionMapper.mapManagedFlushFailure( "error during managed flush", re, this );
}
}
private void managedFlush() {
if ( isClosed() && !waitingForAutoClose ) {
log.trace( "Skipping auto-flush due to session closed" );
return;
}
log.trace( "Automatically flushing session" );
doFlush();
}
注意manageFlush()方法,其中调用了doFlush()方法,而session.flush()调用的也是这个类中的doflush()方法,session中的flush()方法具体源码如下
SessionImpl 类
@Override
public void flush() throws HibernateException {
checkOpen();
doFlush();
}
所以commit 后就不需要flush,flush后还是可以commit的