Вопрос

I'm trying to write a simple application to learn how Transaction works in Spring (Declarative AOP Style). I'm inserting one record into customer table and then throwing NullPointerException to see if the inserted data is rolled back or not. But to my surprise it's not rolling back the data. Here is the code

ApplicationContext.xml file

<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>

This is how I call method

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");

}

And the BoardingService Class Looks like below

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;

    }

and the 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;
}

Not sure where am I going wrong. Any Pointers will be of great help.

Это было полезно?

Решение

You have rollback-for "throwable" instead of "Throwable".

P.S. Not sure that you should use REQUIRES_NEW as the default strategy.

update: From DataSourceTransactionManager documentation

Application code is required to retrieve the JDBC Connection via DataSourceUtils.getConnection(DataSource) instead of a standard J2EE-style DataSource.getConnection() call. Spring classes such as JdbcTemplate use this strategy implicitly. If not used in combination with this transaction manager, the DataSourceUtils lookup strategy behaves exactly like the native DataSource lookup; it can thus be used in a portable fashion.

In your case you open connection directly and then Oracle commits transaction on close(this is a feature of Oracle RDBMS).

Другие советы

You can also just omit the rollback-for attribute. Then it will rollback if any RuntimeException occurs.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top