有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

JavaSpring(5.0.8)事务和jdbcTemplate

我想要一个经典的事务行为:创建a,创建b,如果创建b失败,回滚创建a。
“没那么难,在方法上添加@Transactional spring注释。”
我也是。但它不起作用
我使用的是SpringMVC5.0.8(与SpringTX相同的版本号,在下面的pom.xml中)。数据库是mysql v.5.7.23
首先是我的配置/代码,然后是很多人都会遇到的一些冗余错误

这里是一个服务级别方法

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

以下是数据源、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;
}

这是我的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>

如果您需要更多来自Daos或其他的代码,请询问

编辑1:添加DAO

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

编辑1结束

现在,在互联网上的许多地方都可以找到可能的答案,大部分是:

  • 回滚仅适用于未检查的异常(=RuntimeException)
    BDao抛出一个自定义运行时异常。我在@Transactionnal定义中添加了“rollboor=Exception.class”
  • 由于内部方式@Transactional works(AOP),您必须从方法外部调用它
    在这种情况下,“createB”方法直接从另一个类调用(目前仅从控制器调用)
  • 您必须用这个精确的名称定义一个“transactionManager”
    起初我没有事务管理器。当我意识到这一点时,我感到有点傻。但即使有一个,这个确切的名字,它也不起作用
  • 我甚至发现有人需要添加传播=传播。是必需的,所以我也这么做了,但这并没有改变任何事情
  • 数据库必须支持事务、回滚
    这是一个mysql,所有表上都有InnoDB引擎,根据相同的答案,它支持mysql

现在,我没有任何其他想法,在互联网上也找不到其他想法,所以我来了


共 (1) 个答案

  1. # 1 楼答案

    使用事务时,请确保已在@Configuration上启用了使用@EnableTransactionManagement的事务

    如果没有这个注释,您基本上是在没有事务的情况下运行的,这使得每个操作都在自己的事务中运行