Весна: распространение.ТРЕБУЕТСЯ, не работает

#java #spring #spring-mvc #spring-3 #spring-transactions

#java #весна #spring-mvc #весна-3 #spring-транзакции

Вопрос:

Я вставляю записи в пару таблиц, а именно Dept и Emp . Если Dept таблица успешно создана, то только я хочу вставлять записи в Emp таблицу. Кроме того, если какая-либо вставка завершается Emp неудачно, я хочу откатить всю транзакцию, которая включает как откат Emp , так и Dept таблицы.

Я попробовал это, используя Propagation.REQUIRED , как показано ниже:

Java-файл

 public void saveEmployee(Employee empl){
    try {
        jdbcTemplate.update("INSERT INTO EMP VALUES(?,?,?,?,?)",empl.getEmpId(),empl.getEmpName(),
                empl.getDeptId(),empl.getAge(),empl.getSex());
    } catch (DataAccessException e) {
        e.printStackTrace();
    }

}

@Transactional(propagation=Propagation.REQUIRED)
public void saveRecords(){
    saveDepartment(dept);
    saveEmployee(empl);     
}
  

context.xml

 <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>

<bean id="transactionManager"
    class="org.springframework.jdbc.datasource.DataSourceTransactionManager">        
    <property name="dataSource" ref="dataSource" />
</bean>
  

Проблема:

Даже если вставка в Emp таблицу завершается неудачно, Dept вставка сохраняется, чего я не хочу. Я хочу откатить все.

Пожалуйста, предложите.

Комментарии:

1. Вы перехватываете исключение…

Ответ №1:

Проблема в вашем блоке catch. Поскольку исключение перехвачено, tx не выполняет откат.

Вы должны создать исключение :

 public void saveEmployee(Employee empl){
    try {
        jdbcTemplate.update("INSERT INTO EMP VALUES(?,?,?,?,?)",empl.getEmpId(),empl.getEmpName(),
                empl.getDeptId(),empl.getAge(),empl.getSex());
    } catch (DataAccessException e) {
        e.printStackTrace();
        throw e;
    }

}
  

И, кстати, семантика продвижения.Требуется просто означает: создайте новый tx, если он не существует, ИЛИ используйте существующий, если запущен tx.


После вашего комментария здесь предлагается увидеть эффект НОВОГО tx :

 @Transactional(propagation=Propagation.REQUIRES_NEW)
public void saveEmployee(Employee empl){
    try {
        jdbcTemplate.update("INSERT INTO EMP VALUES(?,?,?,?,?)",empl.getEmpId(),empl.getEmpName(),
                empl.getDeptId(),empl.getAge(),empl.getSex());
    } catch (DataAccessException e) {
        e.printStackTrace();
        throw e;
    }

}

@Transactional(propagation=Propagation.REQUIRED)
public void saveRecords(){
    saveDepartment(dept);
    try{
       saveEmployee(empl);
    }catch(Exception e){Logger.log("Fail to save emp !");}     
}
  

Ключевым моментом, позволяющим увидеть эффект REQUIRE_NEW, является перехват исключения вокруг saveEmployee . Если вы его не поймаете: исключение будет распространяться в другом tx (тот, который начался при вводе saveRecords() ), и он тоже будет откатываться.

Комментарии:

1. Вышеупомянутое решение сработало. Просто для целей тестирования я добавил @Transactional(propagation=Propagation.REQUIRES_NEW) поверх saveEmployee метода, чтобы посмотреть, как он работает. Я ожидал: Dept запись будет сохранена, а Emp запись не будет сохранена, поскольку NEW создаст новую транзакцию. Но я удивлен, увидев результат: Dept ни Emp одна запись не была сохранена. Я что-нибудь пропустил? Пожалуйста, объясните.

2. Почему в этом случае не генерируется исключение? Это потому, что нам нечего откатывать? Кроме того, почему мой фрагмент кода не сработал? Какое значение имеет блок try при вызове saveEmployee метода? Пожалуйста, посоветуйте

3. @user182944 смотрите мою отредактированную правку 😉 С помощью этого примера кода, я думаю, вы увидите, что dept будет сохранен даже при сбое вставки empl

4. да, теперь это работает … но я не могу понять, почему этот блок try имеет такое значение… не могли бы вы объяснить?

5. Спасибо за объяснение, это помогло 🙂