解惑:在spring+hibernate中,只读事务是如何被优化的。
*作者:张荣华(ahuaxuan)
*2007-06-28
*转载请注明出处及作者
*/解惑:在spring+hibernate中,只读事务是如何被优化的。??????? 大家都知道,spring+hibernate的环境下,spring对只读事务会有特别的优化,那么spring是如何做到这个优化的呢??????? ?Without ejb中写到,当事务被标识为只读事务时,某些可以针对只读事务进行优化的资源就可以执行相应的优化措施,比如说hibernate的session在只读事务模式下不会尝试检测和同步持久对象的状态的更新。另外还写到jdbc的connection可以通过调用setReadOnly(true)来切换到只读事务模式上来;但是大多数jdbc driver会忽略掉他。?我们知道spring中所谓的只读事务就是通过设置session的flushmode为never来实现的(http://www.iteye.com/topic/87426)。那么把flushmode设置为never能给我们带来什么呢?我们来看一下hibernate中JDBCTransaction中的方法:java 代码
- publicvoid?commit()?throws?HibernateException?{ ?? ???????if?(!begun)?{ ??
- ???????????thrownew?TransactionException("Transaction?not?successfully?started"); ?? ???????} ??
- ? ?? ???????log.debug("commit"); ??
- ? ?? ???????if?(?!transactionContext.isFlushModeNever()?&&?callback?)?{ ??
- ???????????transactionContext.managedFlush();?//if?an?exception?occurs?during?flush,?user?must?call?rollback() ?? ???????} ??
- //也就是在这里会判断是否需要刷新一级缓存中的持久对象,如果session的flushmode不为//never而且需要回调的话,那么就刷新一级缓存中的持久对象,向数据库发送sql语句 ?? ? ??
- ???????beforeTransactionCompletion(); ?? ???????if?(?callback?)?{ ??
- ???????????jdbcContext.beforeTransactionCompletion(?this?); ?? ???????} ??
- ? ?? ???????try?{ ??
- ???????????commitAndResetAutoCommit(); ?? //提交事务,并且把事务的commit方式设置为auto,是不是和spring在事务开始和事务结束//时设置session的flush?mode的方式是一样的呀。 ??
- ???????????log.debug("committed?JDBC?Connection"); ?? ???????????committed?=?true; ??
- ???????????if?(?callback?)?{ ?? ??????????????jdbcContext.afterTransactionCompletion(?true,?this?); ??
- ???????????} ?? ???????????afterTransactionCompletion(?Status.STATUS_COMMITTED?); ??
- ???????} ?? ???????catch?(SQLException?e)?{ ??
- ???????????log.error("JDBC?commit?failed",?e); ?? ???????????commitFailed?=?true; ??
- ???????????if?(?callback?)?{ ?? ??????????????jdbcContext.afterTransactionCompletion(?false,?this?); ??
- ???????????} ?? ???????????afterTransactionCompletion(?Status.STATUS_UNKNOWN?); ??
- ???????????thrownew?TransactionException("JDBC?commit?failed",?e); ?? ???????} ??
- ???????finally?{ ?? ???????????closeIfRequired(); ??
- ???????} ?? ????} ??
- public?void?managedFlush()?{ ?? ????????if?(?isClosed()?)?{ ??
- ????????????log.trace(?"skipping?auto-flush?due?to?session?closed"?); ?? ????????????return; ??
- ????????} ?? ????????log.trace("automatically?flushing?session"); ??
- ????????flush(); ?? ????????//刷新这个session实例的一级缓存。 ??
- ????????if?(?childSessionsByEntityMode?!=?null?)?{ ?? ????????????Iterator?iter?=?childSessionsByEntityMode.values().iterator(); ??
- ????????????while?(?iter.hasNext()?)?{ ?? ????????????????(?(Session)?iter.next()?).flush(); ??
- ????????????} ?? ????????}//刷新该session的子session的一级缓存。 ??
- ????} ??
- public?void?onFlush(FlushEvent?event)?throws?HibernateException?{ ?? ????????final?EventSource?source?=?event.getSession(); ??
- ????????if?(?source.getPersistenceContext().hasNonReadOnlyEntities()?)?{ ?? ???????????? ??
- ????????????flushEverythingToExecutions(event); ?? //这个方法是flush前的准备工作,它把需要被flush的实体,集合,等等放到需要被flush ??
- //的一个队列中 ?? ????????????performExecutions(source); ??
- //这个方法是最重要的,因为在这里才是真正的执行sql语句,并且负责更新二级缓存(如果你//配置了二级缓存的话) ?? ????????????postFlush(source); ??
- //负责flush后的善后工作,比如说一个对象不再被另外一个对象关联了,那么就把这个对象//从一级缓存重剔除,等等。 ?? ????????????if?(?source.getFactory().getStatistics().isStatisticsEnabled()?)?{ ??
- ????????????????source.getFactory().getStatisticsImplementor().flush(); ?? ????????????} ??
- ???????????? ?? ????????} ??
- ????} ??
作者:张荣华,未经作者同意不得随意转载!
1 楼 annegu 2007-07-23 也就是说在使用spring+hibernate的时候,只读事务就是少一个flush对吧?那使用spring+jdbc的时候,只读事务有哪些优化措施呢?是不是说就没有优化了呀,因为jdbc没有什么flush的说法呀。
2 楼 ahuaxuan 2007-07-24 annegu 写道也就是说在使用spring+hibernate的时候,只读事务就是少一个flush对吧?
那使用spring+jdbc的时候,只读事务有哪些优化措施呢?是不是说就没有优化了呀,因为jdbc没有什么flush的说法呀。
直接使用jdbc好像没有什么优化不优化之说,我不知道把connection设置为readonly到底能带来多少性能的提高,估计没有,而且很多jdbc驱动会忽略这选项,所以直接使用jdbc应该是没有什么特别的优化的 3 楼 xufei0110 2008-05-28 喜欢这样的 文章
在 java方面我还是一个初学者
虽然也能用 Struts Spring Hibernate 等
但 还没有能力 读懂 其源代码
不过 以后会加油的 4 楼 罪恶的小手 2008-06-03 说实话还是有的没看懂,,
也许是我刚接触的问题吧,,
以后努力看吧,,