简体   繁体   English

Spring @Transactional没有回滚

[英]Spring @Transactional not rolling back

I'm using Spring's NamedParameterJdbcTemplate and I'm trying to use @Transactional to make sure that two inserts are either both persisted to the database or one is rolled back, in case the other one fails. 我正在使用Spring的NamedParameterJdbcTemplate ,我正在尝试使用@Transactional来确保两个插入既可以持久保存到数据库,也可以回滚,以防另一个插入失败。

The code is designed to run with MySql and is being tested with H2 in memory. 该代码旨在与MySql一起运行,并在内存中使用H2进行测试。

It's not working... The second insert fails but the first is not rolled back. 它没有用......第二次插入失败但第一次没有回滚。

Here are the relevant classes: 以下是相关课程:

MySpringConfig.java MySpringConfig.java

package com.MyPackage.spring

@Configuration
@ComponentScan({ "com.MyPackage" })
public class MySpringConfig {

@Bean
public NamedParameterJdbcTemplate namedParameterJdbcTemplate() throws Exception {
    return new NamedParameterJdbcTemplate(dataSource());
}

@Bean
public DataSourceTransactionManager dataSourceTransactionManager() throws Exception {
    return new DataSourceTransactionManager(dataSource());
}


@Bean(name = "customerEntitiesDataSource")
public DataSource dataSource() throws Exception {
    Properties properties = new Properties();
    properties.put("url", "db-url");
    properties.put("username", "uName");
    properties.put("password", "pwd");
    BasicDataSource dataSource = BasicDataSourceFactory.createDataSource(properties);
    return dataSource;
}
}

MyDao.java MyDao.java

package com.MyPackage.dao

@Repository
public class MyDao {
    private ObjectMapper mapper = new ObjectMapper();

    @Autowired
    private NamedParameterJdbcTemplate jdbcTemplate;

    private static String INSERT_ELEMENT_QUERY = "INSERT INTO TableA..." + " VALUES (:param1, :param2)";

    @Transactional(rollbackFor = {Exception.class}, propagation=Propagation.REQUIRED)
    public void storeElements(List<Element> element) {


        Stream<HashMap<String, Object>> hashMapStream = elements.stream().map(
                element -> {
                    HashMap<String, Object> params = new HashMap<>();
                    params.put("param1", element.getParam1());
                    params.put("param2", element.getParam2());
                    return params;
                }
        );
        List<Map<String, Object>> collect = hashMapStream.collect(Collectors.<Map<String, Object>>toList());
        Map<String, Object>[] batchValues = new Map[]{};
        batchValues = collect.toArray(batchValues);

        jdbcTemplate.batchUpdate(INSERT_ELEMENT_QUERY, batchValues);

        computers.stream().forEach(element -> saveExtraData(element));
    }


    private static String INSERT_ELEMENT_EXTRA_DATA_QUERY = "INSERT INTO TableB... Values (:val1, :val2)";

    @Transactional(rollbackFor = {Exception.class}, propagation=Propagation.REQUIRED)
    public void saveExtraData(Element element) {

        Stream<HashMap<String, Object>> hashMapStream = element.getExtraData().stream().map(
                extra -> {
                    HashMap<String, Object> params = new HashMap<>();
                    params.put("val1", extra.getVal1());
                    params.put("val2", extra.getVal2());
                    return params;
                }
        );
        List<Map<String, Object>> collect = hashMapStream.collect(Collectors.<Map<String, Object>>toList());
        Map<String, Object>[] batchValues = new Map[]{};
        batchValues = collect.toArray(batchValues);

        jdbcTemplate.batchUpdate(INSERT_ELEMENT_EXTRA_DATA_QUERY , batchValues);
    }
}

The test I'm running is: Send a list of Elements to storeElements() but make sure that one of the elements has an extraData that is too long to be stored in TableB . 我正在运行的测试是:将一个Elements列表发送到storeElements()但要确保其中一个元素的extraData太长而无法存储在TableB I then check the database to make sure that no element was stored in the database. 然后我检查数据库以确保没有元素存储在数据库中。

The insert fails, but there is no rollback. 插入失败,但没有回滚。

The whole code is a Spring stack, from the test, all the way through to the storeElements method. 整个代码是一个Spring堆栈,从测试,一直到storeElements方法。

Running debug, I see that none of the DataSourceTransactionManager methods are called, apart from the constructor, upon it's creation when the Spring context is loaded. 运行调试时,我发现在加载Spring上下文时,除了构造函数之外,没有调用任何DataSourceTransactionManager方法。

What am I missing here? 我在这里错过了什么?

Annotate your MySpringConfig with @EnableTransactionManagement to enable transaction management. 注释您MySpringConfig@EnableTransactionManagement启用事务管理。

@Configuration
@ComponentScan({ "com.MyPackage" })
@EnableTransactionManagement
public class MySpringConfig {

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM