春天@Transactional没有回滚

时间:2017-03-10 14:34:22

标签: java spring

我在@Service

中有类似的代码
@Autowired
private MyDAO myDAO;

@Transactional
@Override
public void m(...) {
    Integer i = null; // this is just to simulate a NPE
    myDAO.saveX(...);
    i.toString(); // throws NullPointerException
    myDAO.saveY(...);
}

这段代码抛出了一个NPE,它没有被Spring捕获,因此我的代码没有回滚。知道为什么会这样吗?

我的配置与我的应用程序中的其他位置相同,并且在那些位置按预期工作。

<jee:jndi-lookup id="dataSource" jndi-name="jdbc/MyDataSource"/>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
</bean>

3 个答案:

答案 0 :(得分:2)

可能的原因:

1)你的bean不是由Spring管理的,a.k.a是用new创建的,而不是从应用程序上下文中获取的。

2)你在同一个类/ bean的另一个方法中调用m()方法。默认情况下,Spring使用代理来管理声明式事务,并且不支持内部调用。

3)你正在抛出已检查的异常,而不是在dao上使用@Reposiotry。声明性事务仅适用于运行时异常。 @Reposiotry通过将所有异常包装在DataAccessException中来“修复”该问题。 (可能不是因为NPE是运行时的情况)

答案 1 :(得分:1)

尝试将rollbackFor参数添加到@Transactional注释

@Transactional(rollbackFor=NullPointerException.class)

答案 2 :(得分:1)

我找到了解决方案here。我有多个上下文,其中一些没有<tx:annotation-driven />