简体   繁体   English

Spring(5.0.8)事务性和jdbcTemplate

[英]Spring (5.0.8) Transactional and jdbcTemplate

I want to have a classic transactional behavior : create a, create b, if creation of b fail, rollback creation of a. 我想要一个经典的事务行为:创建a,创建b,如果创建b失败,则回滚创建a。
"Not so difficult, put an @Transactional spring annotation on your method." “没有那么困难,在您的方法上放置一个@Transactional spring注释。”
So did I. But it doesn't work. 我也是。但这是行不通的。
I'm using spring mvc 5.0.8 (Same version number for spring tx, context, in the below pom.xml). 我正在使用spring mvc 5.0.8(在pom.xml下面的spring tx,上下文具有相同的版本号)。 The database is mysql v.5.7.23 该数据库是mysql v.5.7.23
First, my config/code, then some redundant error many one get. 首先是我的配置/代码,然后是一些很多的冗余错误。

Here is a service-level method. 这是服务级别的方法。

@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public B createB(B b) {
    //some logic to create a, instance of A
    aDao.saveA(a);
    //some logic to create b, instance of B
    return bDao.saveB(b);
}

Here is the datasource, jdbctemplate, and transaction manager config : 这是数据源,jdbctemplate和事务管理器配置:

@Bean
public DataSource dataSource() {
    DriverManagerDataSource dataSource = new DriverManagerDataSource();
    dataSource.setDriverClassName(env.getRequiredProperty("jdbc.driverClassName"));
    dataSource.setUrl(env.getRequiredProperty("jdbc.url"));
    dataSource.setUsername(env.getRequiredProperty("jdbc.username"));
    dataSource.setPassword(env.getRequiredProperty("jdbc.password"));
    return dataSource;
}

@Bean
public JdbcTemplate jdbcTemplate(DataSource dataSource) {
    JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
    jdbcTemplate.setResultsMapCaseInsensitive(true);
    return jdbcTemplate;
}

@Bean("transactionManager")
public PlatformTransactionManager getTransactionManager(DataSource dataSource) {
    DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
    dataSourceTransactionManager.setDataSource(dataSource);
    return dataSourceTransactionManager;
}

Here is a part of my pom.xml : 这是我pom.xml的一部分:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-tx</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
</dependency>

If you need more code, from Daos, or other, please ask. 如果您需要来自Daos或其他的更多代码,请询问。

Edit 1 : Add daos 编辑1:添加daos

@Repository
public class SqlADao implements ADao {
    private static final String CREATE_A = "INSERT INTO a(id, param1,  
    param2) VALUES(?, ?, ?)";

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    public Addressee saveA(A a) {
        try {
            String id = UUID.randomUUID().toString();
            a.setId(id);
            jdbcTemplate.update(CREATE_A, id, a.getParam1(),  
                addressee.getParam2());
            return a;
        } catch (Exception e) {
            throw new DaoException("Exception while accessing data.", e);
        }

    }
}

@Repository
public class SqlBDao implements BDao {

    private static final String CREATE_B = "INSERT INTO b(id, param1,  
    param2, param3, param4, param5, param6) VALUES(?, ?, ?, ?, ?, ?, ?)";

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    public Account saveAccount(Account account) {
        try {
            String id = UUID.randomUUID().toString();
            b.setId(id);
            jdbcTemplate.update(CREATE_B, id, b.getParam1(),  
                Date.valueOf(b.getParam2LocalDate()), b.getParam3,  
                b.getParam4(), b.getParam5(),b.getParam6());
            return b;
        } catch (Exception e) {
            throw new DaoException("Exception while accessing data.", e);
        }
    }
}

End of Edit 1 编辑结束1

Now, possible answer found on many place on the internet, mostly stackoverflow : 现在,可能在互联网上许多地方找到答案,主要是stackoverflow:

  • Rollback work only for unchecked exceptions (=RuntimeException). 回滚仅适用于未经检查的异常(= RuntimeException)。
    The BDao throws a custom RuntimeException. BDao引发自定义RuntimeException。 And I added the "rollbackFor = Exception.class" on the @Transactionnal definition. 我在@Transactionnal定义上添加了“ rollbackFor = Exception.class”。
  • Due to internal way @Transactional works (AOP), you have to call it from outside the method. 由于内部事务@Transactional起作用(AOP),因此必须从方法外部调用它。
    That is the case, the "createB" method is directly called from another class (at the moment, only from a controller". 就是这种情况,“ createB”方法是从另一个类直接调用的(目前,仅从控制器调用)。
  • You have to define a "transactionManager", with this precise name. 您必须使用此精确名称定义“ transactionManager”。
    At first I had no transaction manager. 一开始我没有交易经理。 When I realized, I felt a bit dumb. 当我意识到时,我感到有点傻。 But even with one, with this precise name, it doesn't work. 但是,即使只有一个名称正确的名称,也无法使用。
  • I even found someone who needed to add the propagation=Propagation.REQUIRED, so I did too, but it doesn't change anything. 我什至发现有人需要添加propagation = Propagation.REQUIRED,所以我也这样做了,但是它并没有改变任何东西。
  • The Database have to support transactions, rollback... 数据库必须支持事务,回滚...
    It's a mysql with InnoDB engine on all table, which according to same answers supports it. 这是一个在所有表上都带有InnoDB引擎的mysql,根据相同的答案,它也支持它。

Now, I don't have any other idea, and can't found other ideas on internet, so here I am. 现在,我没有其他想法,也无法在互联网上找到其他想法,所以我在这里。

When using transactions make sure that you have enabled transactions using @EnableTransactionManagement on your @Configuration . 使用事务时,请确保已使用@Configuration上的@EnableTransactionManagement启用了事务。

Without that annotation you are basicly running without transactions and that makes each operation run in its own transactions. 没有该注释,您基本上将没有事务运行,这会使每个操作都在其自己的事务中运行。

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

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