Spring (5.0.8) Transactional и jdbcTemplate - PullRequest
       23

Spring (5.0.8) Transactional и jdbcTemplate

0 голосов
/ 26 августа 2018

Я хочу иметь классическое транзакционное поведение: создать a, создать b, если создание b не удастся, создание отката a.
"Не так уж и сложно, добавьте аннотацию @Transactional spring в свой метод."
Я тоже. Но это не работает.
Я использую spring mvc 5.0.8 (тот же номер версии для Spring tx, context, в приведенном ниже 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: Добавить 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);
        }
    }
}

КонецРедактировать 1

Теперь возможный ответ, найденный во многих местах в Интернете, в основном, через stackoverflow:

  • Откат работает только для непроверенных исключений (= RuntimeException).
    BDao выдаетпользовательские RuntimeException.И я добавил «rollbackFor = Exception.class» в определение @Transactionnal.
  • Из-за внутреннего способа @Transactional работает (AOP), вы должны вызывать его извне метода.
    То естьВ этом случае метод «createB» вызывается напрямую из другого класса (на данный момент, только из контроллера ».
  • Вы должны определить «actionManager» с таким точным именем.
    Сначала яУ меня не было менеджера транзакций. Когда я понял, я почувствовал себя немного глупым. Но даже с одним, с таким точным именем, он не работает.
  • Я даже нашел кого-то, кому нужно было добавить распространение = Распространение.ТРЕБУЕТСЯ, так я и сделал, но это ничего не меняет.
  • База данных должна поддерживать транзакции, откат ...
    Это mysql с движком InnoDB для всех таблиц, который согласно тем же ответамподдерживает его.

Теперь у меня нет другой идеи, и я не могу найти другие идеи в Интернете, поэтому я здесь.

1 Ответ

0 голосов
/ 28 августа 2018

При использовании транзакций убедитесь, что вы включили транзакции, используя @EnableTransactionManagement на вашем @Configuration.

Без этой аннотации вы в основном работаете без транзакций, и каждая операция выполняется в своих собственных транзакциях.

...