如果应用程序中抛出异常,Spring不会回滚事务

时间:2018-11-28 07:23:39

标签: spring spring-mvc spring-boot spring-data spring-transactions

我使用spring事务开发了该应用程序,并将记录插入表中。

我在DAO类中明确抛出了异常,但是spring正在将记录插入表中,而不是回滚事务。

我创建了以下两个应用程序。在情况1中,即使抛出异常,记录也会插入表中。但是在案例2中,没有插入任何记录,并且成功回滚了事务。您能解释一下这两个应用程序之间的区别吗?

情况1:

Item.java

public class Item {

    int itemNo;
    String itemName;
    String itemType;
    String itemSize;
    public int getItemNo() {
        return itemNo;
    }
    public void setItemNo(int itemNo) {
        this.itemNo = itemNo;
    }
    public String getItemName() {
        return itemName;
    }
    public void setItemName(String itemName) {
        this.itemName = itemName;
    }
    public String getItemType() {
        return itemType;
    }
    public void setItemType(String itemType) {
        this.itemType = itemType;
    }
    public String getItemSize() {
        return itemSize;
    }
    public void setItemSize(String itemSize) {
        this.itemSize = itemSize;
    }
}

ItemDao

@Service
public class ItemDao {

    @Autowired
    JdbcTemplate jdbcTemplate ;


    void insert(Item item){

        jdbcTemplate.update("insert into item_test(itemno, itemtype,itemsize,itemname) values (?,?,?,?)", new Object[]{item.getItemNo(),item.getItemType(),item.getItemSize(),item.getItemName()});
        int a=2/0;
    }
}

ItemService.java

@Service
public class ItemService {
    @Autowired
    ItemDao itemDao;    


    @Transactional
    public void insert(Item item){
        try{
            itemDao.insert(item);
        }
        catch(Exception e){
            e.printStackTrace();
        }
    }
}

Test.java

public class Test {

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        ApplicationContext ct = new ClassPathXmlApplicationContext("spring.xml");
        ItemService itemService = ct.getBean("itemService", ItemService.class);

        Item item = new Item();
        item.setItemNo(1234);
        item.setItemName("sofa");
        item.setItemSize("4");
        item.setItemType("furniture");
        itemService.insert(item);
    }

}

spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd   http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd   http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
    <!-- Enable Annotation based Declarative Transaction Management -->
    <tx:annotation-driven proxy-target-class="true" transaction-manager="transactionManager" />
    <context:component-scan base-package="com.spring.springtransaction" />
    <!-- Creating TransactionManager Bean, since JDBC we are creating of type 
        DataSourceTransactionManager -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>
    <!-- MySQL DB DataSource -->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="oracle.jdbc.OracleDriver" />
        <property name="url" value="jdbc:oracle:thin:@locahost:1521:xe)))" />
        <property name="username" value="system" />
        <property name="password" value="system" />
    </bean>
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource" />
    </bean>
    <bean id="itemService" class="com.spring.springtransaction.ItemService" />
</beans>

情况2:

ItemService.java

@Service
public class ItemService {
    @Autowired
    ItemDao itemDao;

    @Autowired
    ItemManger itemManger;

    @Transactional
    public void insert(Item item){
        try{
            itemManger.insert(item);
        }
        catch(Exception e){
            e.printStackTrace();
        }
    }
}

ItemManger.java

@Service
public class ItemManger {

    @Autowired
    ItemDao itemDao;


    @Transactional
    public void insert(Item item){

        itemDao.insert(item);

    }
}

ItemDao.java

@Service
public class ItemDao {

    @Autowired
    JdbcTemplate jdbcTemplate ;


    void insert(Item item){

        jdbcTemplate.update("insert into item_test(itemno, itemtype,itemsize,itemname) values (?,?,?,?)", new Object[]{item.getItemNo(),item.getItemType(),item.getItemSize(),item.getItemName()});
        int a=2/0;
    }
}

2 个答案:

答案 0 :(得分:1)

ItemDao而不是@Repository的身份@Service注释您

您应该使用spring Transactional 上下文而不是main来执行单元测试,例如使用TestNG:

@ContextConfiguration(classes = {ConfigurationClass.class})
@ActiveProfiles({"test"})
public class TestItemDAO extends AbstractTransactionalTestNGSpringContextTests {
    @Autowired
    private ItemDao dao;
    @Test
    public void testItemDao() {
        dao.insert(item);
    }
}

答案 1 :(得分:0)

删除try块,您正在尝试处理异常,因此这就是RollbackException不削减事务流的原因。