Spring:Propagation.REQUIRED无效

时间:2014-06-28 15:33:40

标签: java spring spring-mvc spring-3 spring-transactions

我在几个表中插入记录,即DeptEmp。如果成功创建了Dept表,那么我只想在Emp表中插入记录。此外,如果Emp中的任何插入失败,那么我想回滚所有包含来自EmpDept表的回滚的事务。

我使用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 个答案:

答案 0 :(得分:4)

问题是你的阻塞。由于异常被捕获,因此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;
    }

}

顺便说一句, Progation.Required 的语义只是意味着:如果它不存在则创建一个新的tx或者如果tx正在运行则使用现有的tx。


在您的评论之后,建议您查看NEW 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 !");}     
}

查看REQUIRES_NEW效果的关键是捕获saveEmployee周围的异常。如果你没有捕获它:异常将在另一个tx(输入saveRecords()时启动的那个)中传播,它也会回滚。