1

我正在尝试编写一个简单的应用程序来了解事务在 Spring 中的工作方式(声明式 AOP 样式)。我将一条记录插入到客户表中,然后抛出 NullPointerException 以查看插入的数据是否回滚。但令我惊讶的是,它并没有回滚数据。这是代码

ApplicationContext.xml 文件

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="

    http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
    http://www.springframework.org/schema/tx 
        http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
    http://www.springframework.org/schema/aop 
        http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
    ">

<aop:aspectj-autoproxy />

<bean id="BoardingService" class="com.learning.maven.services.BoardingServiceImpl"/>

<tx:advice id="txAdvice" transaction-manager="transactionManager" >
    <tx:attributes>
        <tx:method name="getUser*" rollback-for="throwable" propagation="REQUIRES_NEW"/>
    </tx:attributes>
</tx:advice>

<aop:config>
    <aop:pointcut id="boardingServiceOperation" expression="execution(* com.learning.maven.services.BoardingService.*(..))"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="boardingServiceOperation"/>
</aop:config>

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

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
    <property name="url" value="jdbc:oracle:thin:@localhost:1521:XE"/>
    <property name="username" value="system"/>
    <property name="password" value="Manager"/>
</bean>

<bean id="customerDAO" class="com.learning.maven.dao.CustomerDAOImpl">
    <property name="dataSource" ref="dataSource" />
</bean>

这就是我调用方法的方式

public static void main(String[] args) {

    context = new FileSystemXmlApplicationContext("C:\\workspace\\learning\\cxf\\SpringTransaction\\cxf.xml");
    BoardingService bean = (BoardingService) context.getBean("BoardingService");
    bean.getUser("1");

}

BoardingService 类如下所示

public class BoardingServiceImpl implements BoardingService, ApplicationContextAware {

    ApplicationContext context = null;

    public String getUser(String id) {

        String response = "SUCCESS";
        try{
            System.out.println("Testing");
            CustomerDAO customerDAO = (CustomerDAO) Testing.context.getBean("customerDAO");

            Customer c = new Customer();
            c.setAge(31);
            c.setCustId(1);
            c.setName("Jagadeesh");


            customerDAO.insert(c);

            customerDAO.insert(null);
        }
        catch(Exception e){
            throw new RuntimeException();
        }

        return response;
    }

    @Override
    public void setApplicationContext(ApplicationContext arg0)
            throws BeansException {
        this.context = arg0;

    }

和 CustomerDAOImpl

private DataSource dataSource;

public void setDataSource(DataSource dataSource) {
    this.dataSource = dataSource;
}

public void insert(Customer customer) {

    String sql = "INSERT INTO CUSTOMER (CUST_ID, NAME, AGE) VALUES (?, ?, ?)";
    Connection conn = null;

    try {
        conn = dataSource.getConnection();
        PreparedStatement ps = conn.prepareStatement(sql);
        ps.setInt(1, customer.getCustId());
        ps.setString(2, customer.getName());
        ps.setInt(3, customer.getAge());
        ps.executeUpdate();
        ps.close();

    } catch (SQLException e) {
        throw new RuntimeException(e);

    } finally {
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {}
        }
    }       
}

public Customer findByCustomerId(int custId) {
    // TODO Auto-generated method stub
    return null;
}

不知道我哪里错了。任何指针都会有很大帮助。

4

2 回答 2

0

你有 rollback-for"throwable"而不是"Throwable".

PS 不确定您是否应该将REQUIRES_NEW其用作默认策略。

更新:来自DataSourceTransactionManager文档

应用程序代码需要通过 DataSourceUtils.getConnection(DataSource) 而不是标准 J2EE 风格的 DataSource.getConnection() 调用来检索 JDBC 连接。JdbcTemplate 等 Spring 类隐式使用此策略。如果不与此事务管理器结合使用,DataSourceUtils 查找策略的行为与本机 DataSource 查找完全相同;因此,它可以以便携式方式使用。

在您的情况下,您直接打开连接,然后 Oracle 在关闭时提交事务(这是 Oracle RDBMS 的一个功能)。

于 2013-01-14T06:29:15.117 回答
0

您也可以省略 rollback-for 属性。然后,如果发生任何 RuntimeException,它将回滚。

于 2013-01-14T06:52:15.560 回答