由于需要大批量的迁移数据(上千万),弄了个迁移工具。

千万的数据,不适宜一次性的提交或回滚事务,中间需要分批提交,在设置事务的过程中,居然发现spring的声明式事务中设置的方法read-only级别无效。

见下面代码:

<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
    <tx:method name="add*" propagation="REQUIRED"/>
    <tx:method name="save*" propagation="REQUIRED"/>
    <tx:method name="insert*" propagation="REQUIRED"/>
    <tx:method name="del*" propagation="REQUIRED"/>
    <tx:method name="update*" propagation="REQUIRED"/>
    <tx:method name="*" read-only="true"/>
    </tx:attributes>
</tx:advice>

上面的设置,任何的方法都可以更新或者删除数据,read-only形同虚设。

但是当抛出异常时查看数据,发现又都是回滚的,说明事务还是起作用的,

同样的代码,弄在我自己的小项目中,read-only又起作用了,这就奇怪了。

查询资料后发现,原来是数据库的原因,我自己的小项目使用的是mysql,而当前项目中是oracle,oracle的官方文档上有这么一句:

Read-only connections are supported by the Oracle server, but not by the Oracle JDBC drivers.

原来是Oracle Read Only 隔离级别只是支持Oracle Server,并不支持jdbc驱动,所以spring中虽然设置了read-only,仍旧不起作用!

顺便贴上spring的事务级别:

PROPAGATION_REQUIRED -- 支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。 
PROPAGATION_SUPPORTS -- 支持当前事务,如果当前没有事务,就以非事务方式执行。 
PROPAGATION_MANDATORY -- 支持当前事务,如果当前没有事务,就抛出异常。 
PROPAGATION_REQUIRES_NEW -- 新建事务,如果当前存在事务,把当前事务挂起。 
PROPAGATION_NOT_SUPPORTED -- 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。 
PROPAGATION_NEVER -- 以非事务方式执行,如果当前存在事务,则抛出异常。 
PROPAGATION_NESTED -- 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。 
前六个策略类似于EJB CMT,第七个(PROPAGATION_NESTED)是Spring所提供的一个特殊变量。 
它要求事务管理器或者使用JDBC 3.0 Savepoint API提供嵌套事务行为(如Spring的DataSourceTransactionManager)
你可能感兴趣的内容
0条评论

selfly

交流QQ群:32261424
Owner