rss· 投稿· 设为首页· 加入收藏· 繁體版
当前位置: 火魔网 » 程序开发 » Java基础

测试spring事务中readonly

最新测试结果 start...: ahuaxuan 在回复中说的没错,在DataSourceUtils.prepareConnectionForTransaction(con, definition)中的确会设置readonly,我之前说的DataSourceTransactionManager中不设置readonly的说法是错误的。
但在oracle下,这个readonly确实有问题,我一步步测下来,原因就是出在 con.setAutoCommit(false) 这行代码上:
1. 如果 con.setReadOnly(true) 放在 con.setAutoCommit(false) 前面,就是代码现在的做法,readonly是不起作用的。
2. 反之,如果我把DataSourceUtils.prepareConnectionForTransaction(con, definition)  代码放在它的后面的时候,readonly 起了作用。
难道oracle的驱动对这个顺序还有影响吗,有点匪夷所思啊。
不知道在其他数据库中有没有影响。

Java代码
  • //其中, DataSourceUtils.prepareConnectionForTransaction(con, definition)中会设置con.setReadOnly(true)   
  • protected void doBegin(Object transaction, TransactionDefinition definition) {   
  • ....   
  • ....   
  • Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);   
  •             txObject.setPreviousIsolationLevel(previousIsolationLevel);   
  •   
  •             // Switch to manual commit if necessary. This is very expensive in some JDBC drivers,   
  •             // so we don't want to do it unnecessarily (for example if we've explicitly   
  •             // configured the connection pool to set it already).   
  •                
  •             if (con.getAutoCommit()) {   
  •                    
  •                 txObject.setMustRestoreAutoCommit(true);   
  •                    
  •                 if (logger.isDebugEnabled()) {   
  •                     logger.debug("Switching JDBC Connection [" + con + "] to manual commit");   
  •                 }   
  •                 con.setAutoCommit(false);   
  •             }   
  • ...   
  • ...   
  • }  
  • //其中, DataSourceUtils.prepareConnectionForTransaction(con, definition)中会设置con.setReadOnly(true)
    protected void doBegin(Object transaction, TransactionDefinition definition) {
    ....
    ....
    Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
    txObject.setPreviousIsolationLevel(previousIsolationLevel);
    // Switch to manual commit if necessary. This is very expensive in some JDBC drivers,
    // so we don't want to do it unnecessarily (for example if we've explicitly
    // configured the connection pool to set it already).
    if (con.getAutoCommit()) {
    txObject.setMustRestoreAutoCommit(true);
    if (logger.isDebugEnabled()) {
    logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
    }
    con.setAutoCommit(false);
    }
    ...
    ...
    }
    
    最新测试结果 end...
    为何readonly不起作用,有人真正测过吗? 环境
    1. spring2.5 + ibatis/jdbctemplate(测了这两个) + oracle10,
    2. 驱动ojdbc14.jar
    3. 连接池 dbcp和c3p0都测了。 先看部分后台,证明调用的方法确实开启了readonly:
    Java代码
  • 21/01/2009 16:43:01,457 <DEBUG> (org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource)- Adding transactional method [search*] with attribute [PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly]   
  •   
  •   
  • 21/01/2009 17:10:00,864 <DEBUG> (org.springframework.jdbc.datasource.DataSourceTransactionManager)- Creating new transaction with name [com.me.service.logic.ViewService.searchLeave]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly  
  • 21/01/2009 16:43:01,457 <DEBUG> (org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource)- Adding transactional method [search*] with attribute [PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly]
    21/01/2009 17:10:00,864 <DEBUG> (org.springframework.jdbc.datasource.DataSourceTransactionManager)- Creating new transaction with name [com.me.service.logic.ViewService.searchLeave]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly
    
    先在oracle里面测试下
    Java代码
  • set transaction read only;   
  • update stu set title = 'oh,god' where id='12345'  
  • set transaction read only;
    update stu set title = 'oh,god' where id='12345'
    

    抛错,证明oracle对read only有效:
    Java代码
  • ORA-01456: may not perform insert/delete/update operation inside a READ ONLY transaction  
  • ORA-01456: may not perform insert/delete/update operation inside a READ ONLY transaction
    

    Xml代码
  • <aop:config>  
  •     <aop:pointcut id="serviceOperation"  
  •         expression="execution(* com.me.service.logic.*ServiceImpl.*(..))" />  
  •     <aop:advisor pointcut-ref="serviceOperation" advice-ref="txAdvice" />  
  • </aop:config>  
  •   
  • <tx:advice id="txAdvice" transaction-manager="transactionManager">  
  •     <tx:attributes>  
  •         <tx:method name="search*" read-only="true" />  
  •     </tx:attributes>  
  • </tx:advice>  
  • 	<aop:config>
    <aop:pointcut id="serviceOperation"
    expression="execution(* com.me.service.logic.*ServiceImpl.*(..))" />
    <aop:advisor pointcut-ref="serviceOperation" advice-ref="txAdvice" />
    </aop:config>
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
    <tx:method name="search*" read-only="true" />
    </tx:attributes>
    </tx:advice>
    
    Java代码
  • //ViewServiceImpl:   
  • public List searchLeave(Leave leave) {   
  •        
  •         //update stu set title = 'oh,god' where id='12345'   
  •         int j = viewDAO.updateStu();   
  •            
  •     return viewDAO.searchLeave(leave);   
  • }  
  • //ViewServiceImpl:
    public List searchLeave(Leave leave) {
            //update stu set title = 'oh,god' where id='12345'
            int j = viewDAO.updateStu();
    return viewDAO.searchLeave(leave);
    }
    
    以上的searchLeave方法应该抛出错误的。readonly不允许update。
    顶一下
    (0)
    踩一下
    (0)