精华帖 (1) :: 良好帖 (7) :: 新手帖 (0) :: 隐藏帖 (1)
|
|||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
作者 | 正文 | ||||||||||||||||||||||
发表时间:2011-08-14
最后修改:2011-08-14
用过Hibernate的人都知道Hibernate最原始的使用Session方式(异常忽略):
当然还有另外一个方法getCurrentSession() 这个方法就是通过SessionContext来减少Session创建的。比如常用的ThreadLocalSessionContext:
Session current = existingSession( factory ); if (current == null) { current = buildOrObtainSession(); current.getTransaction().registerSynchronization( buildCleanupSynch() ); if ( needsWrapping( current ) ) { current = wrap( current ); } doBind( current, factory ); } return current;
currentSession()内部先从ThreadLocal中获取Session。若不为null直接返回,若为null则openSession(...)一个Session并把这个Session对象绑定在ThreadLocal上。它就是通过在ThreadLocal中注册绑定Session来确保线程中最多只有一个Session对象。
上面的地球人都知道 ==============================================================================
Spring提供许多Template对各种底层ORM等进行集成,如JdbcTemplate、HibernateTemplate、JpaTemplate等同时也提供了相应的Dao模板类,如JdbcDaoSupport、HibernateDaoSupport、JpaDaoSupport等
getSession和getCurrentSession实现过程差不多,但是精简了SessionContext那一段。并且可以设置allowCreate,如果设置为false,此方法应该和getCurrentSession同样效果。
=========================================================================
了解了这些之后、我进行了一个HibernateTemplate和getSession之间的测试,主要就是测试 单线程下多次重复请求创建Session与事务之间的关系、HibernateTemplate和getSession()两者之间在功能实现和效率上有什么样的不同。(多线程下卡的要死、不测试了)
第一次测试
第二次测试
第三次测试
第四次测试
总结: getSession()在事务边界内会通过TransactionSynchronizationManager获取Session资源,同一线程内它不会重复创建Connection , 那些获取到的Session()不需要手动关闭。但是在无声明式事务环境下,它就会表现出极其坑爹的状况,它反复获取Connection,也不关闭Session。非常消耗资源
HibernateTemplate有一个安全且高效的Session环境,它的CRUD都是位于HibernateCallback内部,如果它的CRUD并没有位于事务之中,它会自己创建一个事务(Spring集成Hibernate时,所有的资源都是由TransactionSynchronizationManager管理的 )。同一个线程中它只需要一个Connection。Session也会在事务边界处自动关闭,程序员不需要关注此事(这个事务边界可能是@Transactional显式声明的也可能是HibernateTemplate#doExecute隐式声明的)。
在同一个事务边界内,两个HibernateTemplate操作内部的Session互也不相同这个问题可以在HibernateTemplate源码中找到答案: protected <T> T doExecute(HibernateCallback<T> action, boolean enforceNewSession, boolean enforceNativeSession) throws DataAccessException { ...... Session session = (enforceNewSession ? SessionFactoryUtils.getNewSession(getSessionFactory(), getEntityInterceptor()) : getSession()); boolean existingTransaction = (!enforceNewSession && (!isAllowCreate() || SessionFactoryUtils.isSessionTransactional(session, getSessionFactory()))); if (existingTransaction) { logger.debug("Found thread-bound Session for HibernateTemplate"); } FlushMode previousFlushMode = null; try { previousFlushMode = applyFlushMode(session, existingTransaction); enableFilters(session); Session sessionToExpose = (enforceNativeSession || isExposeNativeSession() ? session : createSessionProxy(session)); T result = action.doInHibernate(sessionToExpose); flushIfNecessary(session, existingTransaction); return result; ...... } 通过 Session sessionToExpose = (enforceNativeSession || isExposeNativeSession() ? session : createSessionProxy(session)); 红色部分可以看到HibernateTemplate中获取的Session不是原生的,而是代理的。那个代理类是一个比较简单的内部类,源代码位于HibernateTemplate类文件最下部分。每次HibernateTemplate#doExecute执行时除非声明不使用代理类,Spring都会使用线程中的Session资源来创建代理。但是这个代理类的创建对性能的影响微不足道了,Spring这样做肯定有它的道理。
各位英雄好汉,不要乱投新手帖、隐藏贴奥。 咱琢磨了好几天的东西,你们高手们就不要否决了 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|||||||||||||||||||||||
返回顶楼 | |||||||||||||||||||||||
发表时间:2011-08-14
ItEye的编辑功能真愁人、 弄了一个小时还是这熊样。。。
为什么一个通过 SessionFactory.getStatistics().getTransactionCount()获取的Transaction数量 是通过 SessionFactory.getStatistics().getSessionOpenCount()获取的Session数量 的两倍呢???? 难道一个Session都需要Spring创建两个Transaction??? |
|||||||||||||||||||||||
返回顶楼 | |||||||||||||||||||||||
发表时间:2011-08-15
哇,楼主你好棒耶……
|
|||||||||||||||||||||||
返回顶楼 | |||||||||||||||||||||||
发表时间:2011-08-15
用过Hibernate的人都知道Hibernate最原始的使用Session方式(异常忽略):
当然还有另外一个方法getCurrentSession() 这个方法就是通过SessionContext来减少Session创建的。比如常用的ThreadLocalSessionContext:
Session current = existingSession( factory ); if (current == null) { current = buildOrObtainSession(); current.getTransaction().registerSynchronization( buildCleanupSynch() ); if ( needsWrapping( current ) ) { current = wrap( current ); } doBind( current, factory ); } return current;
currentSession()内部先从ThreadLocal中获取Session。若不为null直接返回,若为null则openSession(...)一个Session并把这个Session对象绑定在ThreadLocal上。它就是通过在ThreadLocal中注册绑定Session来确保线程中最多只有一个Session对象。
上面的地球人都知道 ==============================================================================
Spring提供许多Template对各种底层ORM等进行集成,如JdbcTemplate、HibernateTemplate、JpaTemplate等同时也提供了相应的Dao模板类,如JdbcDaoSupport、HibernateDaoSupport、JpaDaoSupport等
getSession和getCurrentSession实现过程差不多,但是精简了SessionContext那一段。并且可以设置allowCreate,如果设置为false,此方法应该和getCurrentSession同样效果。
=========================================================================
了解了这些之后、我进行了一个HibernateTemplate和getSession之间的测试,主要就是测试 单线程下多次重复请求创建Session与事务之间的关系、HibernateTemplate和getSession()两者之间在功能实现和效率上有什么样的不同。(多线程下卡的要死、不测试了)
第一次测试
第二次测试
第三次测试
第四次测试
总结: getSession()在事务边界内会通过TransactionSynchronizationManager获取Session资源,同一线程内它不会重复创建Connection , 那些获取到的Session()不需要手动关闭。但是在无声明式事务环境下,它就会表现出极其坑爹的状况,它反复获取Connection,也不关闭Session。非常消耗资源
HibernateTemplate有一个安全且高效的Session环境,它的CRUD都是位于HibernateCallback内部,如果它的CRUD并没有位于事务之中,它会自己创建一个事务(Spring集成Hibernate时,所有的资源都是由TransactionSynchronizationManager管理的 )。同一个线程中它只需要一个Connection。Session也会在事务边界处自动关闭,程序员不需要关注此事(这个事务边界可能是@Transactional显式声明的也可能是HibernateTemplate#doExecute隐式声明的)。
在同一个事务边界内,两个HibernateTemplate操作内部的Session互也不相同这个问题可以在HibernateTemplate源码中找到答案: protected <T> T doExecute(HibernateCallback<T> action, boolean enforceNewSession, boolean enforceNativeSession) throws DataAccessException { ...... Session session = (enforceNewSession ? SessionFactoryUtils.getNewSession(getSessionFactory(), getEntityInterceptor()) : getSession()); boolean existingTransaction = (!enforceNewSession && (!isAllowCreate() || SessionFactoryUtils.isSessionTransactional(session, getSessionFactory()))); if (existingTransaction) { logger.debug("Found thread-bound Session for HibernateTemplate"); } FlushMode previousFlushMode = null; try { previousFlushMode = applyFlushMode(session, existingTransaction); enableFilters(session); Session sessionToExpose = (enforceNativeSession || isExposeNativeSession() ? session : createSessionProxy(session)); T result = action.doInHibernate(sessionToExpose); flushIfNecessary(session, existingTransaction); return result; ...... } 通过 Session sessionToExpose = (enforceNativeSession || isExposeNativeSession() ? session : createSessionProxy(session)); 红色部分可以看到HibernateTemplate中获取的Session不是原生的,而是代理的。那个代理类是一个比较简单的内部类,源代码位于HibernateTemplate类文件最下部分。每次HibernateTemplate#doExecute执行时除非声明不使用代理类,Spring都会使用线程中的Session资源来创建代理。但是这个代理类的创建对性能的影响微不足道了,Spring这样做肯定有它的道理。
|
|||||||||||||||||||||||
返回顶楼 | |||||||||||||||||||||||
发表时间:2011-08-16
我擦,好帖木人回复,戳帖全都来骂。无语了,先顶一个再说。
|
|||||||||||||||||||||||
返回顶楼 | |||||||||||||||||||||||
发表时间:2011-08-16
http://www.iteye.com/topic/733971
|
|||||||||||||||||||||||
返回顶楼 | |||||||||||||||||||||||
发表时间:2011-08-16
楼主分析的不错,如果用openinsessionview可以getSession也可以自动关闭,前提是配置事务
|
|||||||||||||||||||||||
返回顶楼 | |||||||||||||||||||||||
发表时间:2011-08-16
受益了..
|
|||||||||||||||||||||||
返回顶楼 | |||||||||||||||||||||||
发表时间:2011-08-16
rentianchou 写道 楼主分析的不错,如果用openinsessionview可以getSession也可以自动关闭,前提是配置事务
那样的话,要为每个线程都打开Session的啊 真正操作时候并不需要的, 比如用户注册账号, 经常是填写多次才能合法注册。 也就是多个Request可能有一个需要打开Session, 其他的都不需要打开Session,否则就是资源浪费 |
|||||||||||||||||||||||
返回顶楼 | |||||||||||||||||||||||
发表时间:2011-08-16
写的挺好!!
|
|||||||||||||||||||||||
返回顶楼 | |||||||||||||||||||||||