为了弄清楚spring对session和事务的管理以及OpenSessionInViewFilter是如何工作的,可监控以下类的日志:
org.springframework.orm.hibernate3.support.OpenSessionInViewFilter,
org.springframework.orm.hibernate3.HibernateTransactionManager,
org.hibernate.transaction.JDBCTransaction,
org.hibernate.impl.SessionImpl
具体可参考下面的配置:
<appender name="sessionTransactionAppender" class="org.apache.log4j.DailyRollingFileAppender"> <param name="File" value="session_transaction.log" /> <param name="Append" value="false" /> <param name="Threshold" value="DEBUG" /> <param name="DatePattern" value="'.'yyyy-MM-dd" /> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="[%t] %d %-5p [%c] %m%n" /> </layout> </appender> <category name="org.hibernate.impl.SessionImpl"> <priority value="ALL" /> <appender-ref ref="sessionTransactionAppender"/> </category> <category name="org.springframework.orm.hibernate3.HibernateTransactionManager"> <priority value="ALL" /> <appender-ref ref="sessionTransactionAppender"/> </category> <category name="org.springframework.orm.hibernate3.support.OpenSessionInViewFilter"> <priority value="debug" /> <appender-ref ref="sessionTransactionAppender"/> </category>
下面是在一个不使用OpenSessionInViewFilter的项目中,一次请求(所有条目都是在一个线程里的)调用两次getAllForumGroups方法(此方法上声明了事务控制)打出的日志:
日志中可以清楚地看到:每次事务开启时会打开一个新的session,事务结束时会关闭该session,session不再和当前线程绑定。
[7143355@qtp-21544349-0] 2011-03-28 15:39:33,304 DEBUG [org.hibernate.impl.SessionImpl] opened session at timestamp: 5330116498333696[7143355@qtp-21544349-0] 2011-03-28 15:39:33,698 DEBUG [org.springframework.orm.hibernate3.HibernateTransactionManager] Creating new transaction with name [oobbs.application.service.forum.ForumGroupService.getAllForumGroups]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT[7143355@qtp-21544349-0] 2011-03-28 15:39:33,700 DEBUG [org.hibernate.impl.SessionImpl] opened session at timestamp: 5330116500275200[7143355@qtp-21544349-0] 2011-03-28 15:39:33,701 DEBUG [org.springframework.orm.hibernate3.HibernateTransactionManager] Opened new Session [org.hibernate.impl.SessionImpl@a0e220] for Hibernate transaction[7143355@qtp-21544349-0] 2011-03-28 15:39:33,712 DEBUG [org.springframework.orm.hibernate3.HibernateTransactionManager] Preparing JDBC Connection of Hibernate Session [org.hibernate.impl.SessionImpl@a0e220][7143355@qtp-21544349-0] 2011-03-28 15:39:33,737 DEBUG [org.hibernate.transaction.JDBCTransaction] begin[7143355@qtp-21544349-0] 2011-03-28 15:39:33,739 DEBUG [org.hibernate.transaction.JDBCTransaction] current autocommit status: true[7143355@qtp-21544349-0] 2011-03-28 15:39:33,740 DEBUG [org.hibernate.transaction.JDBCTransaction] disabling autocommit[7143355@qtp-21544349-0] 2011-03-28 15:39:33,746 DEBUG [org.springframework.orm.hibernate3.HibernateTransactionManager] Exposing Hibernate transaction as JDBC transaction [org.apache.commons.dbcp.PoolableConnection@1ac9683][7143355@qtp-21544349-0] 2011-03-28 15:39:34,205 DEBUG [org.hibernate.impl.SessionImpl] initializing proxy: [oobbs.domainmodel.user.User#-1][7143355@qtp-21544349-0] 2011-03-28 15:39:34,419 DEBUG [org.springframework.orm.hibernate3.HibernateTransactionManager] Initiating transaction commit[7143355@qtp-21544349-0] 2011-03-28 15:39:34,423 DEBUG [org.springframework.orm.hibernate3.HibernateTransactionManager] Committing Hibernate transaction on Session [org.hibernate.impl.SessionImpl@a0e220][7143355@qtp-21544349-0] 2011-03-28 15:39:34,426 DEBUG [org.hibernate.transaction.JDBCTransaction] commit[7143355@qtp-21544349-0] 2011-03-28 15:39:34,447 DEBUG [org.hibernate.transaction.JDBCTransaction] re-enabling autocommit[7143355@qtp-21544349-0] 2011-03-28 15:39:34,452 DEBUG [org.hibernate.transaction.JDBCTransaction] committed JDBC Connection[7143355@qtp-21544349-0] 2011-03-28 15:39:34,458 DEBUG [org.springframework.orm.hibernate3.HibernateTransactionManager] Closing Hibernate Session [org.hibernate.impl.SessionImpl@a0e220] after transaction[7143355@qtp-21544349-0] 2011-03-28 15:39:34,464 DEBUG [org.springframework.orm.hibernate3.HibernateTransactionManager] Creating new transaction with name [oobbs.application.service.forum.ForumGroupService.getAllForumGroups]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT[7143355@qtp-21544349-0] 2011-03-28 15:39:34,465 DEBUG [org.hibernate.impl.SessionImpl] opened session at timestamp: 5330116503408640[7143355@qtp-21544349-0] 2011-03-28 15:39:34,466 DEBUG [org.springframework.orm.hibernate3.HibernateTransactionManager] Opened new Session [org.hibernate.impl.SessionImpl@f7d5a6] for Hibernate transaction[7143355@qtp-21544349-0] 2011-03-28 15:39:34,469 DEBUG [org.springframework.orm.hibernate3.HibernateTransactionManager] Preparing JDBC Connection of Hibernate Session [org.hibernate.impl.SessionImpl@f7d5a6][7143355@qtp-21544349-0] 2011-03-28 15:39:34,470 DEBUG [org.hibernate.transaction.JDBCTransaction] begin[7143355@qtp-21544349-0] 2011-03-28 15:39:34,474 DEBUG [org.hibernate.transaction.JDBCTransaction] current autocommit status: true[7143355@qtp-21544349-0] 2011-03-28 15:39:34,476 DEBUG [org.hibernate.transaction.JDBCTransaction] disabling autocommit[7143355@qtp-21544349-0] 2011-03-28 15:39:34,478 DEBUG [org.springframework.orm.hibernate3.HibernateTransactionManager] Exposing Hibernate transaction as JDBC transaction [org.apache.commons.dbcp.PoolableConnection@1ac9683][7143355@qtp-21544349-0] 2011-03-28 15:39:34,652 DEBUG [org.hibernate.impl.SessionImpl] initializing proxy: [oobbs.domainmodel.user.User#-1][7143355@qtp-21544349-0] 2011-03-28 15:39:34,795 DEBUG [org.springframework.orm.hibernate3.HibernateTransactionManager] Initiating transaction commit[7143355@qtp-21544349-0] 2011-03-28 15:39:34,796 DEBUG [org.springframework.orm.hibernate3.HibernateTransactionManager] Committing Hibernate transaction on Session [org.hibernate.impl.SessionImpl@f7d5a6][7143355@qtp-21544349-0] 2011-03-28 15:39:34,798 DEBUG [org.hibernate.transaction.JDBCTransaction] commit[7143355@qtp-21544349-0] 2011-03-28 15:39:34,804 DEBUG [org.hibernate.transaction.JDBCTransaction] re-enabling autocommit[7143355@qtp-21544349-0] 2011-03-28 15:39:34,805 DEBUG [org.hibernate.transaction.JDBCTransaction] committed JDBC Connection[7143355@qtp-21544349-0] 2011-03-28 15:39:34,810 DEBUG [org.springframework.orm.hibernate3.HibernateTransactionManager] Closing Hibernate Session [org.hibernate.impl.SessionImpl@f7d5a6] after transaction
下面是在一个使用了OpenSessionInViewFilter的项目中,一次请求(所有条目都是在一个线程里的)调用两次getRole方法(此方法上声明了事务控制)打出的日志:
日志中可以清楚地看到:请求刚发起时就会创建一个session实例,并绑定到当前线程上,至请求结束时,关闭该线程。在请求期间所有事务都使用这一个session。
另一方面我们还可以看到:数据库连接connection保持打开的时间正是事务从开始到提交的时间,为了测试,getRole方法中故意设定了3秒的延迟,从日志上看出数据库连接也基本上维持了3秒。这是很多系统出现无法获取数据库连接问题的原因。在一个使用了连接池的系统里,连接数有一个最大上限,如果某个请求的处理耗时过长,则当前数据库连接在短时间内就得不到释放。当前并发访问量急速上升时,连接池的连接用会迅速用光,导致后续的请求因无法得到数据库连接而失败。
最后,至于为什么只需要保证session一直打开就能避免lazy loading时不报错,原因就在于,观察下面的log可以发现,每当在事务期间时autocommit就被禁用,事务一执行完毕就又恢复至可用。这样,在jsp页面上读取lazy对象时,并不是以事务方式进行的,而是以autocommit的方式提交select语句的。因此只需要保持session打开即可,无需事务的支持。
[http-8080-4] 2011-03-28 15:25:59,367 DEBUG [org.springframework.orm.hibernate3.support.OpenSessionInViewFilter] Using SessionFactory 'sessionFactory' for OpenSessionInViewFilter[http-8080-4] 2011-03-28 15:25:59,367 DEBUG [org.springframework.orm.hibernate3.support.OpenSessionInViewFilter] Opening single Hibernate Session in OpenSessionInViewFilter[http-8080-4] 2011-03-28 15:25:59,367 DEBUG [org.hibernate.impl.SessionImpl] opened session at timestamp: 5330113164767232[http-8080-4] 2011-03-28 15:25:59,439 DEBUG [org.springframework.orm.hibernate3.HibernateTransactionManager] Found thread-bound Session [org.hibernate.impl.SessionImpl@1d8f985] for Hibernate transaction[http-8080-4] 2011-03-28 15:25:59,439 DEBUG [org.springframework.orm.hibernate3.HibernateTransactionManager] Creating new transaction with name [sf.demo.RoleService.getRole]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT;[http-8080-4] 2011-03-28 15:25:59,439 DEBUG [org.springframework.orm.hibernate3.HibernateTransactionManager] Preparing JDBC Connection of Hibernate Session [org.hibernate.impl.SessionImpl@1d8f985][http-8080-4] 2011-03-28 15:25:59,439 DEBUG [org.hibernate.transaction.JDBCTransaction] begin[http-8080-4] 2011-03-28 15:25:59,439 DEBUG [org.hibernate.transaction.JDBCTransaction] current autocommit status: true[http-8080-4] 2011-03-28 15:25:59,439 DEBUG [org.hibernate.transaction.JDBCTransaction] disabling autocommit[http-8080-4] 2011-03-28 15:25:59,440 DEBUG [org.springframework.orm.hibernate3.HibernateTransactionManager] Exposing Hibernate transaction as JDBC transaction [com.mchange.v2.c3p0.impl.NewProxyConnection@16f7142][http-8080-4] 2011-03-28 15:26:02,440 DEBUG [org.springframework.orm.hibernate3.HibernateTransactionManager] Initiating transaction commit[http-8080-4] 2011-03-28 15:26:02,440 DEBUG [org.springframework.orm.hibernate3.HibernateTransactionManager] Committing Hibernate transaction on Session [org.hibernate.impl.SessionImpl@1d8f985][http-8080-4] 2011-03-28 15:26:02,440 DEBUG [org.hibernate.transaction.JDBCTransaction] commit[http-8080-4] 2011-03-28 15:26:02,442 DEBUG [org.hibernate.transaction.JDBCTransaction] re-enabling autocommit[http-8080-4] 2011-03-28 15:26:02,443 DEBUG [org.hibernate.transaction.JDBCTransaction] committed JDBC Connection[http-8080-4] 2011-03-28 15:26:02,443 DEBUG [org.springframework.orm.hibernate3.HibernateTransactionManager] Not closing pre-bound Hibernate Session [org.hibernate.impl.SessionImpl@1d8f985] after transaction[http-8080-4] 2011-03-28 15:26:02,443 DEBUG [org.hibernate.impl.SessionImpl] disconnecting session[http-8080-4] 2011-03-28 15:26:02,445 DEBUG [org.springframework.orm.hibernate3.HibernateTransactionManager] Found thread-bound Session [org.hibernate.impl.SessionImpl@1d8f985] for Hibernate transaction[http-8080-4] 2011-03-28 15:26:02,445 DEBUG [org.springframework.orm.hibernate3.HibernateTransactionManager] Creating new transaction with name [sf.demo.RoleService.getRole]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT;[http-8080-4] 2011-03-28 15:26:02,445 DEBUG [org.springframework.orm.hibernate3.HibernateTransactionManager] Preparing JDBC Connection of Hibernate Session [org.hibernate.impl.SessionImpl@1d8f985][http-8080-4] 2011-03-28 15:26:02,445 DEBUG [org.hibernate.transaction.JDBCTransaction] begin[http-8080-4] 2011-03-28 15:26:02,445 DEBUG [org.hibernate.transaction.JDBCTransaction] current autocommit status: true[http-8080-4] 2011-03-28 15:26:02,446 DEBUG [org.hibernate.transaction.JDBCTransaction] disabling autocommit[http-8080-4] 2011-03-28 15:26:02,446 DEBUG [org.springframework.orm.hibernate3.HibernateTransactionManager] Exposing Hibernate transaction as JDBC transaction [com.mchange.v2.c3p0.impl.NewProxyConnection@1fb8de1][http-8080-4] 2011-03-28 15:26:05,447 DEBUG [org.springframework.orm.hibernate3.HibernateTransactionManager] Initiating transaction commit[http-8080-4] 2011-03-28 15:26:05,447 DEBUG [org.springframework.orm.hibernate3.HibernateTransactionManager] Committing Hibernate transaction on Session [org.hibernate.impl.SessionImpl@1d8f985][http-8080-4] 2011-03-28 15:26:05,447 DEBUG [org.hibernate.transaction.JDBCTransaction] commit[http-8080-4] 2011-03-28 15:26:05,449 DEBUG [org.hibernate.transaction.JDBCTransaction] re-enabling autocommit[http-8080-4] 2011-03-28 15:26:05,450 DEBUG [org.hibernate.transaction.JDBCTransaction] committed JDBC Connection[http-8080-4] 2011-03-28 15:26:05,450 DEBUG [org.springframework.orm.hibernate3.HibernateTransactionManager] Not closing pre-bound Hibernate Session [org.hibernate.impl.SessionImpl@1d8f985] after transaction[http-8080-4] 2011-03-28 15:26:05,450 DEBUG [org.hibernate.impl.SessionImpl] disconnecting session[http-8080-4] 2011-03-28 15:26:08,680 DEBUG [org.springframework.orm.hibernate3.support.OpenSessionInViewFilter] Closing single Hibernate Session in OpenSessionInViewFilter
再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow