`

Hibernate(20):默认情况下决定commit时session命运的三个条件

阅读更多

    Hibernate(十九): 异常"Session was already closed" 中,针对"Session was already closed"异常,我们发现最终调用了transactionContext.managedClose方法来关掉了session, 那么这个过程具体是什么样的? 这篇中将加以梳理 .

    在JDBCTransaction类(Transaction接口的一个实现类)具体决定是否要关session的方法closeIfRequired 里, 有这么一个复合条件决断: if(callback && transactionContext.shouldAutoClose() && !transactionContext.isClosed() ). 这三个条件分别代表什么?

    首先看这个
callback, 在 JDBCTransaction 类的begin方法里(session.beginTransaction()方法最终要调用这个begin),看到这样的赋值: callback = jdbcContext.registerCallbackIfNecessary();
   
registerCallbackIfNecessary方法的实现有些奇怪, 如下所示:

     public boolean registerCallbackIfNecessary() {
        if ( isTransactionCallbackRegistered ) {
            return false;
        }
        else {
            isTransactionCallbackRegistered = true;
            return true;
        }
    }
   
如果isTransactionCallbackRegistered 为true就返回false, 如果是false,把它set为true后返回true. 有些奇怪. 不过, 这里不过多讨论了, debug时发现这里返回的是true.

    再看第二个
transactionContext.shouldAutoClose().这里的主角transactionContextTransactionFactory.Context接口, 它什么时候set到 JDBCTransaction 类的, JDBCTransaction类的构造方法里,即JDBCTransaction(JDBCContext jdbcContext, TransactionFactory.Context transactionContext). 为了追 transactionContext是从哪来的,看 这个构造方法又是何时调用. JDBCTransactionFactory里的createTransaction方法, 这个方法又在JDBCContext类的createTransaction( this, owner ) 里,这里的的owner就是我们一直追的transactionContext, 那么这个owner是什么它又来自何方呢? 来自JDBCContext(Context owner, Connection connection, Interceptor interceptor)构造方法.如下是整个跟踪路径:


最终在SessionImpl类的构造方法里对jdbcContext的赋值语句看到了,owner就是this,即SessionImpl对象.

    this.jdbcContext = new JDBCContext( this, connection, interceptor );
也就是说SessionImpl类实现了TransactionFactory.Context接口(以实现JDBCContext.Context子接口方式间接来的).
    看到这里, 根源找到了, 也就是说transactionContext.shouldAutoClose()是要调用 SessionImpl类的shouldAutoClose方法, shouldAutoClose方法 又 有调用isAutoCloseSessionEnabled() && !isClosed(),最终看到是看isAutoCloseSessionEnabled方法里的autoCloseSessionEnabled属 性. 那这么个属性又是何时set的,源头在哪?

    可从下图的方法调用栈,看到了源头: ThreadLocalSessionContext类里的isAutoCloseEnabled方法,
通过"return true;"写死的!

这 里有一个不舒服的地方: SessionImpl实现了JDBCContext.Context接口, 虽说接口JDBCContext.Context继承自TransactionFactory.Context,但让SessionImpl这么早地就跟 具体JDBCXXXX绑定还是有些别扭, 有些畸形.

    对第二个条件的跟踪很是艰辛, 下面看第三个条件: !transactionContext.isClosed(), 应该说有了上面很是艰辛的分析后, 这里很自然地得知这里的第三个条件是调用了 SessionImpl 实现类的相应方法. (这里有个注意点: isClosed方法恰好也是SessionImplementor接口定义的,这样在SessionImpl(父类)里一石二鸟地对两个接口定义的方法 做了实现, 再往一想,是不是可以抽出一个接口closable,让SessionImplementor和TransactionFactory.Context两 个接口做下继承?)

1
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics