1.session.beginTransaction()和transaction.commit()
session.beginTransation()做了什么事。看如下代码:
public Transaction beginTransaction() throws HibernateException {
errorIfClosed();
if ( rootSession != null ) {
// todo : should seriously consider not allowing a txn to begin from a child session
// can always route the request to the root session
log.warn( "Transaction started on non-root session" );
}
Transaction result = getTransaction();
result.begin();
return result;
}
这个方法中的result是一个org.hibernate.transaction.JDBCTransaction实例,而方法中的getTransaction()方法源代码为:
public Transaction getTransaction() throws HibernateException {
if (hibernateTransaction==null) {
log.error(owner.getFactory().getSettings()
.getTransactionFactory().getClass());
hibernateTransaction = owner.getFactory().getSettings()
.getTransactionFactory()
.createTransaction( this, owner );
}
return hibernateTransaction;
}
再次追踪,owner.getFactory().getSettings() .getTransactionFactory()的createTransaction()方法源代码如下:
public Transaction createTransaction(JDBCContext jdbcContext, Context transactionContext)
throws HibernateException {
return new JDBCTransaction( jdbcContext, transactionContext );
}
它返回了一个JDBCTransaction,没什么特别的。
JDBCTransaction执行了result.begin():
public void begin() throws HibernateException {
if (begun) {
return;
}
if (commitFailed) {
throw new TransactionException("cannot re-start transaction after failed commit");
}
log.debug("begin");
try {
toggleAutoCommit = jdbcContext.connection().getAutoCommit();
if (log.isDebugEnabled()) {
log.debug("current autocommit status: " + toggleAutoCommit);
}
if (toggleAutoCommit) {
log.debug("disabling autocommit");
jdbcContext.connection().setAutoCommit(false);//把自动提交设为了false
}
} catch (SQLException e) {
log.error("JDBC begin failed", e);
throw new TransactionException("JDBC begin failed: ", e);
}
callback = jdbcContext.registerCallbackIfNecessary();
begun = true;
committed = false;
rolledBack = false;
if (timeout > 0) {
jdbcContext.getConnectionManager().getBatcher().setTransactionTimeout(timeout);
}
jdbcContext.afterTransactionBegin(this);
}
在直接使用Hibernate时,要在事务结束的时候,写上一句:tx.commit(),这个commit()的源码为:
public void commit() throws HibernateException {
if (!begun) {
throw new TransactionException("Transaction not successfully started");
}
log.debug("commit");
if (!transactionContext.isFlushModeNever() && callback) {
transactionContext.managedFlush(); // if an exception occurs during
// flush, user must call
// rollback()
}
notifyLocalSynchsBeforeTransactionCompletion();
if (callback) {
jdbcContext.beforeTransactionCompletion(this);
}
try {
commitAndResetAutoCommit();//重点代码,它的作用是提交事务,并把connection的autocommit属性恢复为true
log.debug("committed JDBC Connection");
committed = true;
if (callback) {
jdbcContext.afterTransactionCompletion(true, this);
}
notifyLocalSynchsAfterTransactionCompletion(Status.STATUS_COMMITTED);
} catch (SQLException e) {
log.error("JDBC commit failed", e);
commitFailed = true;
if (callback) {
jdbcContext.afterTransactionCompletion(false, this);
}
notifyLocalSynchsAfterTransactionCompletion(Status.STATUS_UNKNOWN);
throw new TransactionException("JDBC commit failed", e);
} finally {
closeIfRequired();
}
}
上面代码中,commitAndResetAutoCommit()方法的源码如下:
private void commitAndResetAutoCommit() throws SQLException {
try {
jdbcContext.connection().commit();//这段不用说也能理解了
} finally {
toggleAutoCommit();//这段的作用是恢复connection的autocommit属性为true
}
}
上述代码的toggleAutoCommit()源代码如下:
private void toggleAutoCommit() {
try {
if (toggleAutoCommit) {
log.debug("re-enabling autocommit");
jdbcContext.connection().setAutoCommit(true);//这行代码的意义很明白了吧
}
} catch (Exception sqle) {
log.error("Could not toggle autocommit", sqle);
}
}
因此,如果你是直接使用hibernate,并手动管理它的session,并手动开启事务关闭事务的话,完全可以保证你的事务。
总结:
1.所谓事务提交就是指执行:connection().commit()。事务自动提交就是每一条sql语句会自动执行connection().commit()。
事务自动提交称之为没有开启事务,手动提交称之为开启事务。
2.hibernate的配置文件hibernate.cfg.xml中可以设置hibernate的事务提交方式(默认是false:即手动提交):
<property name="hibernate.connection.autocommit">true</property>
原始的jdbcconnection默认是自动提交的即没有开启事务,通过设置hibernate.connection.autocommit属性可以设置connection默认的提交方式。即设置toggleAutoCommit属性。
3.session.beginTransaction()内在操作:
(1)开启事务,即设置autoCommit属性为false:
if (toggleAutoCommit){
log.debug("disablingautocommit");
jdbcContext.connection().setAutoCommit(false);
}
4.session.getTransaction().commit()内在操作:
(1)事务提交:jdbcContext.connection().commit()
(2)恢复事务提交方式:
if (toggleAutoCommit) {
log.debug("re-enablingautocommit");
jdbcContext.connection().setAutoCommit(true );
}