@Transactional 不适用于 Spring Boot 和 JDBC

pab*_*blo 5 java spring spring-boot

我的服务应该将数据保存到父数据库表和子数据库表中,并在发生错误时回滚。我尝试使用硬编码强制错误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);
    }
}
Run Code Online (Sandbox Code Playgroud)

服务层:

    @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, ...);
    }

}
Run Code Online (Sandbox Code Playgroud)

道:

public void saveData(jdbcTemplate, ...){
    saveDataInParentDatatable(jdbcTemplate, ...);
    saveDataInChildDatatable(jdbcTemplate, ...);
}
private void saveDataInChildDatatable(jdbcTemplate, ...){
    throw new RuntimeException();
}
Run Code Online (Sandbox Code Playgroud)

bra*_*ndf 5

我遇到了类似的问题。我假设您正在 MyBean 的另一个方法中调用 MyBean.saveData 方法。

\n\n

经过多次搜索、尝试和失败后,我找到了这个链接:http ://ignaciosuay.com/why-is-spring-ignoring-transactional/

\n\n

其中解释了当调用的方法位于调用它的同一个类中时,@Transactional 注释将被忽略。Spring对此的解释是:

\n\n
\n

\xe2\x80\x9c在代理模式(默认)下,仅拦截通过代理传入的外部方法调用。这意味着,自调用实际上是目标对象中的方法调用目标对象的另一个方法,即使调用的方法标有@,也不会在运行时导致实际的事务。交易性的。另外,代理必须完全初始化才能提供预期的行为,因此您不应在初始化代码中依赖此功能,即 @PostConstruct。\xe2\x80\x9d

\n
\n\n

所以我创建了另一个类来封装我的 DAO 方法调用,并使用它的方法来代替,并且它起作用了。

\n\n

所以对于这种情况,它可能是这样的:

\n\n

我的豆:

\n\n
@Service\npublic class MyBean {\n\n    MyBean2 bean2;\n\n    public void saveData(...){\n        bean2.saveData(jdbcTemplate, ...);\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

我的豆2:

\n\n
@Service\npublic class MyBean2 {\n\n    private final NamedParameterJdbcTemplate jdbcTemplate;        \n    private final MyDAO myDao;\n\n    @Autowired\n    public MyBean2 (NamedParameterJdbcTemplate jdbcTemplate, MyDAO myDao) {\n        this.jdbcTemplate = jdbcTemplate;\n        this.myDao= myDao;\n    }\n\n    @Override\n    @Transactional\n    public void saveData(...){\n        myDao.saveData(jdbcTemplate, ...);\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n


小智 1

推荐使用:

@Transactional(rollbackFor = {Exception.class, RuntimeException.class})
Run Code Online (Sandbox Code Playgroud)