簡體   English   中英

@Transactional 不適用於 Spring Boot 和 JDBC

[英]@Transactional not working with Spring Boot and JDBC

我的服務應該將數據保存到父和子數據庫表,並在發生錯誤時回滾。 我嘗試使用硬編碼的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, ...);
    }

}

道:

public void saveData(jdbcTemplate, ...){
    saveDataInParentDatatable(jdbcTemplate, ...);
    saveDataInChildDatatable(jdbcTemplate, ...);
}
private void saveDataInChildDatatable(jdbcTemplate, ...){
    throw new RuntimeException();
}

我遇到了類似的問題。 我假設您在 MyBean 的另一個方法中調用 MyBean.saveData 方法。

經過多次搜索、嘗試和失敗,我找到了這個鏈接: http : //ignaciosuay.com/why-is-spring-ignoring-transactional/

其中解釋了當被調用的方法在調用它的同一個類中時,@Transactional 注釋被忽略。 Spring對其的解釋是:

“在代理模式下(默認),只有通過代理進入的外部方法調用才會被攔截。 這意味着自調用實際上是目標對象中的一個方法調用目標對象的另一個方法,即使被調用的方法用@Transactional 標記,也不會在運行時導致實際事務。 此外,代理必須完全初始化以提供預期的行為,因此您不應在初始化代碼中依賴此功能,即@PostConstruct。”

所以我創建了另一個類來封裝我的 DAO 方法調用,而是使用它的方法並且它起作用了。

所以對於這種情況,它可能是這樣的:

我的豆:

@Service
public class MyBean {

    MyBean2 bean2;

    public void saveData(...){
        bean2.saveData(jdbcTemplate, ...);
    }
}

我的豆2:

@Service
public class MyBean2 {

    private final NamedParameterJdbcTemplate jdbcTemplate;        
    private final MyDAO myDao;

    @Autowired
    public MyBean2 (NamedParameterJdbcTemplate jdbcTemplate, MyDAO myDao) {
        this.jdbcTemplate = jdbcTemplate;
        this.myDao= myDao;
    }

    @Override
    @Transactional
    public void saveData(...){
        myDao.saveData(jdbcTemplate, ...);
    }
}

嘗試這個:

@Transactional(propagation = Propagation.MANDATORY, rollbackFor = Exception.class)

推薦使用:

@Transactional(rollbackFor = {Exception.class, RuntimeException.class})

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM