hibernate,spring管理事务中(transaction,JDBC connection,Hibernate Session的使用研究)

首先hibernate的Connection release mode有以下几种:
1 after_statement 2 after_transaction 3 on_close 其中after_statement 用在jta中 ,on_close 是3.1之前遗留的(也许是为spring留的-_-),也就是3.1之前默认是on_close ,但3.1之后默认如果单独使用hibernate是after_transaction,如果有第三方事务管理,就用第三方提供的默认值,spring就是默认使用了on_close。
在spring管理事务中我们看看系统启动后默认使用的配置:
1,ransaction strategy: org.springframework.orm.hibernate3.SpringTransactionFactory使用spring事务策略
2,hibernate内部 Automatic session close at end of transaction: disabled 因为已经交给spring了
3   Connection release mode: auto 默认,也就是没有配置hibernate.connection.release_mode的时候,但是这里有地方需要注意:也就是前面提到的使用第三方策略时的问题:看一下代码:
String releaseModeName = PropertiesHelper.getString( Environment.RELEASE_CONNECTIONS, properties, "auto" );
        log.info( "Connection release mode: " + releaseModeName );
        ConnectionReleaseMode releaseMode;
        if ( "auto".equals(releaseModeName) ) {
            releaseMode = transactionFactory.getDefaultReleaseMode();      
} else {
            releaseMode = ConnectionReleaseMode.parse( releaseModeName );
         if ( releaseMode == ConnectionReleaseMode.AFTER_STATEMENT && !connections.supportsAggressiveRelease() ) {
                log.warn( "Overriding release mode as connection provider does not support 'after_statement'" );
                releaseMode = ConnectionReleaseMode.AFTER_TRANSACTION;
            }
        }
其中红色部分就是调用了spring提供的默认值,而spring的默认值:在jta和cmt中都默认使用的是after_statement
/** *//**
     * Sets connection release mode "on_close" as default.
     * <p>This was the case for Hibernate 3.0; Hibernate 3.1 changed
     * it to "auto" (i.e. "after_statement" or "after_transaction").
     * However, for Spring's resource management (in particular for
     * HibernateTransactionManager), "on_close" is the better default.
     */
    public ConnectionReleaseMode getDefaultReleaseMode() {
        return ConnectionReleaseMode.ON_CLOSE;
    }

而spring为什么要使用on_close ,而不是用after_transaction ,我们想想opensessioninview的原理也许能明白,session在view成还要使用,所以不能再transaction使用完后关闭JDBC connection,必须要在session之后,所以要使用on_close(也就是在on session(flush.auto,或者flush.Eagerly) 关闭)。这种情况hibernate内部还会在spring关闭JDBC connection后提示(费解,因为after transaction之后session没有关闭,但是 Connection release mode配置的是on_close,session的关闭和 Connection 的关闭都由spring来管理,hibernate就不知道了),所以hibernate有好的提示如下(其实session,已经关闭。当然随着session的关闭jdbc链接释放回连接池):
transaction completed on session with on_close connection release mode; be sure to close the session to release JDBC resources!,

。当然我们也可以使用after_transaction ,这种情况对使用编程式事务非常适用。

org.hibernate.connection包的主要封装了通过JDBC来连接数据库的操作,用户可以以数据源的方式,或者通过特定数据库驱动的方式,甚至是自己定义连接类的方式来完成数据库的连接操作,包下面的代码文件并不多,只有5个,分别是ConnectionProviderFactory.java,ConnectionProvider.java,DriverManagerConnectionProvider.java,DatasourceConnectionProvider.java,UserSuppliedConnectionProvider.java,其中ConnectionProvider是一个接口,DriverManagerConnectionProvider、DatasourceConnectionProvider、UserSuppliedConnectionProvider分别继承了这个接口,而ConnectionProviderFactory则是一个工厂类,他的主要作用是调用ConnectionProvider接口,而不关心接口的具体实现是DriverManagerConnectionProvider或者DatasourceConnectionProvider还是UserSuppliedConnectionProvider。

    首先来看ConnectionProvider接口,提供了如下几个方法:   

1.configure()方法主要是根据配置文件来初始化所有的连接信息。   

2.getConnection()方法抓取一个连接。   

3.closeConnection(Connection conn)方法关闭某个特定连接。   

4.close()关闭所有连接。   

5.supportsAggressiveRelease()方法和hibernate.connection.release_mode配置参数有关,该参数用来指定使用哪一种连接释放模式。HIBERNATE参考手册是这样描的:     Hibernate关于JDBC连接管理的旧(2.x)行为是,Session在第一次需要的时候获取一个连接,在session关闭之前一直会持有这个连接。Hibernate引入了连接释放的概念,来告诉session如何处理它的JDBC连接。注意,下面的讨论只适用于采用配置ConnectionProvider来提供连接的情况,用户自己提供的连接与这里的讨论无关。通过org.hibernate.hibernate.connection.release_mode的不同枚举值来使用不用的释放模式:    

     ON_CLOSE - 基本上就是上面提到的老式行为。Hibernate session在第一次需要进行JDBC操作的时候获取连接,然后持有它,直到session关闭。

     AFTER_TRANSACTION - 在org.hibernate.Transaction结束后释放连接。

     AFTER_STATEMENT (也被称做积极释放) - 在每一条语句被执行后就释放连接。但假若语句留下了与session相关的资源,那就不会被释放。目前唯一的这种情形就是使用org.hibernate.ScrollableResults 

     auto(默认) - 这一选择把释放模式委派给org.hibernate.transaction.TransactionFactory.getDefaultReleaseMode()方法。对JTATransactionFactory来说,它会返回hibernate.connection.release_mode.AFTER_STATEMENT;对JDBCTransactionFactory来说,则是hibernate.connection.release_mode.AFTER_TRANSACTION。很少需要修改这一默认行为,因为假若设置不当,就会带来bug,或者给用户代码带来误导。

     on_close - 使用 hibernate.connection.release_mode.ON_CLOSE. 这种方式是为了向下兼容的,但是已经完全不被鼓励使用了。

     after_transaction - 使用hibernate.connection.release_mode.AFTER_TRANSACTION。这一设置不应该在JTA环境下使用。也要注意,使用hibernate.connection.release_mode.AFTER_TRANSACTION的时候,假若session 处于auto-commit状态,连接会像AFTER_STATEMENT那样被释放。

     after_statement - 使用hibernate.connection.release_mode.AFTER_STATEMENT。除此之外,会查询配置的ConnectionProvider,是否它支持这一设置((supportsAggressiveRelease()))。假若不支持,释放模式会被设置为hibernate.connection.release_mode.AFTER_TRANSACTION。只有在你每次调用ConnectionProvider.getConnection()获取底层JDBC连接的时候,都可以确信获得同一个连接的时候,这一设置才是安全的;或者在auto-commit环境中,你可以不管是否每次都获得同一个连接的时候,这才是安全的。也就是说supportsAggressiveRelease()返回false的时候,释放模式会被设置为hibernate.connection.release_mode.AFTER_TRANSACTION。如果返回true,只表示它支持使用hibernate.connection.release_mode.AFTER_STATEMENT这一个设置,并不表示一定使用这个设置

1 首先connection.autocommit配置成false的情况:
     此种情况需要手动开启事务,需要手动开启transaction,以及提交transaction,并且此时transaction.auto_close_session配置的配置将自动设置为false,所以此时如果connection.release_mode配置为on_close()时需要手动关闭session才能释放JDBC 连接,日志会提示:
transaction completed on session with on_close connection release mode; be sure to close the session to release JDBC resources!
因此connection.autocommit为false的情况建议connection.release_mode采取默认auto。

2 connection.autocommit为true的情况,此时不需要手动开启transaction以及提交transaction,hibernate自动开始transaction并在每次操作后提交transaction,设置此   时transaction.auto_close_session设置将自动为false。 如果connection.release_mode配置为on_close()是需要手动关闭session才能释放JDBC 连接.建议此种情况connection.release_mode设置默认auto。

3 connection.autocommit为true的情况,如果此时又手动开启了transaction,此时connection.autocommit将被设置为false(disabling autocommit),需要手动提交transaction,此种情况如同第一种情况。

猜你喜欢

转载自ssydxa219.iteye.com/blog/1569668