我的服务应该将数据保存到父数据库表和子数据库表,并在出现错误时回滚。我尝试使用硬编码的RuntimeException
强制执行错误,并发现无论如何都要提交事务。
我错过了什么?
我使用的是Spring Boot 2,包括spring-boot-starter-jdbc
依赖项。
数据库是Oracle 11g。
主要配置:
@SpringBootApplication
@EnableTransactionManagement
public class MyApplication extends SpringBootServletInitializer{
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(MyApplication.class);
}
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
服务层:
@Service
public class MyBean {
private final NamedParameterJdbcTemplate jdbcTemplate;
private final MyDAO myDao;
@Autowired
public MyBean (NamedParameterJdbcTemplate jdbcTemplate, MyDAO myDao) {
this.jdbcTemplate = jdbcTemplate;
this.myDao= myDao;
}
@Override
@Transactional
public void saveData(...){
myDao.saveData(jdbcTemplate, ...);
}
}
DAO:
public void saveData(jdbcTemplate, ...){
saveDataInParentDatatable(jdbcTemplate, ...);
saveDataInChildDatatable(jdbcTemplate, ...);
}
private void saveDataInChildDatatable(jdbcTemplate, ...){
throw new RuntimeException();
}
答案 0 :(得分:1)
我遇到了类似的问题。我假设您正在使用MyBean的另一个方法调用MyBean.saveData方法。
经过大量搜索,尝试和失败之后,我找到了以下链接:http://ignaciosuay.com/why-is-spring-ignoring-transactional/
其中解释说,当被调用的方法与被调用的方法位于同一类中时,@ Transactional注释将被忽略。其Spring explanation是:
“在代理模式(默认)下,仅外部方法调用 通过代理进入的邮件被拦截。这意味着 自我调用实际上是目标对象内的一种方法 目标对象的另一种方法,不会导致实际 运行时的事务,即使被调用的方法标记有 @交易。另外,必须完全初始化代理以提供 预期的行为,因此您不应该依赖于此功能 初始化代码,即@PostConstruct。”
所以我创建了另一个类来封装我的DAO方法调用,改用了它的方法,并且可以正常工作。
因此,在这种情况下,可能类似于:
MyBean:
@Service
public class MyBean {
MyBean2 bean2;
public void saveData(...){
bean2.saveData(jdbcTemplate, ...);
}
}
MyBean2:
@Service
public class MyBean2 {
private final NamedParameterJdbcTemplate jdbcTemplate;
private final MyDAO myDao;
@Autowired
public MyBean (NamedParameterJdbcTemplate jdbcTemplate, MyDAO myDao) {
this.jdbcTemplate = jdbcTemplate;
this.myDao= myDao;
}
@Override
@Transactional
public void saveData(...){
myDao.saveData(jdbcTemplate, ...);
}
}
答案 1 :(得分:0)
推荐使用:
@Transactional(rollbackFor = {Exception.class, RuntimeException.class})
答案 2 :(得分:0)
试试这个:
@Transactional(propagation = Propagation.MANDATORY, rollbackFor = Exception.class)