我有一个问题在过去几天一直困扰着我,我似乎无法弄明白。我已经看了很多关于它的问题,但似乎找不到适合我的问题。
情景
我有一个服务bean,其注释方法使用@Transactional(rollbackFor=DaoException.class)
此方法调用DAO,该DAO调用与DB2 AS400数据库交互的JdbcTemplate。我的配置xml看起来像这样:
<tx:annotation-driven proxy-target-class="true" transactionManager="txManager" />
<bean id="txManager" class="org.springframework.jdbc.core.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="dataSource" class="com.ibm.as400.access.AS400JDBCConnectionPoolDataSource">
<property name=... value=... />
...
...
</bean>
<!-- Uses constructor injection to get dao -->
<bean id="service" class="com.my.package.service.MyService" />
<!-- Same, but for the JdbcTemplate -->
<bean id="dao" class="com.my.package.dao.MyDao" />
<bean id="template" class="org.springframework.blah.blah.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
好的,所以当你查看日志时这一切似乎都有效。 TransactionManager注册,它在调用方法时打开一个事务,将JDBC连接设置为手动提交,然后声称在抛出异常时调用数据库上的回滚。
但是!事实并非如此。
DAO在我的数据库表上发出DELETE
,删除了两行。然后应该发出INSERT
来添加两个新行。我已经将代码更改为在删除后抛出所需的异常。这似乎引起txManager
,但效果不存在......数据库中的行仍然缺失。
但是,如果我将<property name="autoCommit" value="false" />
添加到dataSource
bean,那么相同的过程实际上会起作用。数据保留在数据库中。这让我不确定我做对了。我很确定有旧的代码可能会受到关闭自动提交的影响...
我唯一能补充的是,在撰写本文时,我不确定@Transaction
注释中的异常是否是未经检查的异常。我已经读过,检查过的异常不会导致回滚。但如果是这种情况,为什么日志看起来恰恰相反。我通过DataSourceTransaction管理器代码进行了调试,它也调用了它的回滚方法。
我的问题:
什么可能导致spring看起来像是按照日志进行回滚,但实际上并没有执行它。并且,当autoCommit设置为false时,为什么会发生回滚。
编辑:我将更新checked-vs-unchecked异常理论