hibernate 之session 事务管理

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(truethis);
            }
            notifyLocalSynchsAfterTransactionCompletion(Status.STATUS_COMMITTED);
        } catch (SQLException e) {
            log.error("JDBC commit failed", e);
            commitFailed = true;
            if (callback) {
                jdbcContext.afterTransactionCompletion(falsethis);
            }
            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 );

                     }

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值