我在@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>
答案 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 />
。