近期在看Spring的事物管理,模拟情况是在同一个方法里面执行两次数据库更新操作,一次成功,一次失败 抛出SQLException,目的是想让这两次操作在同一个事物中,如果一个失败,两个操作都将会滚。
遇到的问题是,其中一条更新正常执行,一条更新由于抛出异常没有执行,个人感觉是Spring 的事物没有起作用。下面是相关的Spring 配置 以及 Java代码
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    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/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">                        <!-- scan the package and the sub package -->
    <context:component-scan base-package="com.book" />    <!-- don't handle the static resource -->
    <mvc:default-servlet-handler />    <!-- if you use annotation you must configure following setting -->
    <mvc:annotation-driven />    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">  
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />  
    <property name="url" value="jdbc:mysql://localhost/book" />  
    <property name="username" value="xxx" />  
    <property name="password" value="xxx" />
</bean>    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
      <property name="dataSource" ref="dataSource" />
  </bean> <!-- enable transaction annotation support -->
  <tx:annotation-driven transaction-manager="txManager"/>    <!-- configure the InternalResourceViewResolver -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" 
            id="internalResourceViewResolver">
        <!-- 前缀 -->
        <property name="prefix" value="/WEB-INF/" />
        <!-- 后缀 -->
        <property name="suffix" value=".jsp" />
    </bean>
    <bean id="com.book.service.BookLocalService" class="com.book.service.impl.BookLocalServiceImpl"></bean>
    <bean id="com.book.dao.DBHelper" class="com.book.dao.DBHelper"></bean>
    
</beans>
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Java 代码部分import java.sql.PreparedStatement;
import java.sql.SQLException;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;import com.book.dao.DBHelper;
import com.book.service.BookLocalService;public class BookLocalServiceImpl implements BookLocalService{ private String sql = "insert into book (name,price) values(?,?);";

@Transactional(propagation=Propagation.REQUIRED,readOnly=false,rollbackFor=SQLException.class)
@Override
public void addBook(String name, String price) throws SQLException {

PreparedStatement pst = _dbHelper.createPST(sql);
try {
pst.setString(1, "test");
pst.setString(2, "100");
pst.execute();
pst.setString(1, name);
pst.setString(2, price);
pst.execute();
}
catch (SQLException e) {
throw e ;
}
finally{
_dbHelper.closeConnection();
}
}

@Autowired
private DBHelper _dbHelper;
}我在方法上面添加了@Transactional(propagation=Propagation.REQUIRED,readOnly=false,rollbackFor=SQLException.class)
理论上应该是当我添加非法数据导致throw SQLException的时候,两个数据库更新操作都应该回滚
当前的问题之前描述过,就是其中的一个数据库更新成功,另外一个失败,个人感觉Spring Transaction没有起作用。
谁能给分析下原因并给予解决方案?
万分感谢!

解决方案 »

  1.   

    确定走了catch块吗?
      

  2.   

    感谢回复,确定走了catch块,console已经抛出了SQLException。
      

  3.   


    感谢回复,确定走了catch块,console已经抛出了SQLException。
      

  4.   

    不用进行try  catch   只有抛出异常时rollbackfor才会起作用
      

  5.   


    首先感谢回复
    我的代码中虽然添加了try  catch 语句块,但是catch 内,我仍然做了 throw  exception操作,我这里用try catch 之后又进行throw 只是为了用finally 去关闭连接。并且  我把try catch移除之后也做了测试,仍然是不好用的。
      

  6.   

    DBHelper 中的数据源用的是spring管理的数据源吗? 我看你并没有注入,是从代码中获取的?