请教一个关于spring事务的问题 ?

05-11-24 zgli

由于问题较长,希望各位高手能够耐心看完,谢谢, 数据库mysql.

CREATE TABLE `CUSTOMERS` (
`id` BIGINT NOT NULL AUTO_INCREMENT,
`name` VARCHAR(45) NOT NULL,
`sex` VARCHAR(45) NOT NULL,
`age` INTEGER NOT NULL,
PRIMARY KEY(`id`)
)
ENGINE = InnoDB;

所有jdbc实现的dao基类

public class DAO {
    DataSource dataSource;
	public void setDataSource(DataSource dataSource)
		throws DataAccessException {
		this.dataSource = dataSource;
	}
}


ICustomerDAO接口

public interface ICustomerDAO {	
	Long insertCustomer(Customer customer)throws DataAccessException;
}
<p class="indent">


ICustomerDAO接口的实现类CustomerDAO_Imp继承DAO实现ICustomerDAO

public class CustomerDAO_Imp extends DAO implements ICustomerDAO {

	public Long insertCustomer(Customer customer) throws DataAccessException {
		Long result = null;
		Connection conn = null;
		try {
			conn = dataSource.getConnection();
			String sql = "INSERT INTO CUSTOMERS(name,sex,age)values(?,?,?);";
			PreparedStatement pstmt = conn.prepareStatement(sql);
			pstmt.setString(1, customer.getName());
			pstmt.setString(2, customer.getSex());
			pstmt.setInt(3, customer.getAge());
			pstmt.execute();
			pstmt.close();
			Statement stmt = conn.createStatement();
			ResultSet rs = stmt.executeQuery("select max(id) from CUSTOMERS ;");
			rs.next();
			result = new Long(rs.getLong(1));
			rs.close();
			stmt.close();
			return result;
		} catch (SQLException e) {
			e.printStackTrace();
			throw new DataAccessException(e.getMessage());
		} finally {
			try {
				conn.close();
			} catch (SQLException e1) {
				e1.printStackTrace();
				throw new DataAccessException(e1.getMessage());
			}
		}
	}

服务接口

	public interface IService {
	void method1();
	}

IService服务接口实现类Service_Imp
public class Service_Imp implements IService {

ICustomerDAO customerDAO;
public void setCustomerDAO(ICustomerDAO customerDAO) {
this.customerDAO = customerDAO;
}

public void method1() { //fail
Customer customer = new Customer();
customer.setName("Jim");
customer.setSex("Male");
customer.setAge(24);
Long cid = customerDAO.insertCustomer(customer);
Order order = new Order();

System.out.println(
"customers table should not contains customer with id " + cid);

int i = 1 / 0; //exception in service method

}
配置文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING/DTD BEAN/EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
    <bean id="dataSource"
          class="org.apache.commons.dbcp.BasicDataSource"
          destroy-method="close">
       <property name="driverClassName">
           <value>org.gjt.mm.mysql.Driver</value>
       </property>
       <property name="url">
           <value>jdbc:mysql://localhost/test</value>
       </property>
       <property name="username"><value>root</value></property>
       <property name="password"><value>root</value></property>
    </bean> 
    
    <bean id="transactionManager"
          class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
       <property name="dataSource">
           <ref local="dataSource" />
       </property>
    </bean>
    
    <bean id="customerDAO" class="dao.imp.jdbc.CustomerDAO_Imp">
      <property name="dataSource">
        <ref local="dataSource" />
      </property>
    </bean>  
    
    <bean id="serviceImp"
          class="service.imp.Service_Imp">      
       <property name="customerDAO">
          <ref local="customerDAO" />
       </property>
    </bean>      
    
    <bean id="service"
          class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
       <property name="transactionManager">
          <ref bean="transactionManager" />
       </property>
       <property name="target">
          <ref local="serviceImp" />
       </property>
       <property name="transactionAttributes">
          <props>
            <prop key="*">PROPAGATION_REQUIRED</prop>
          </props>
       </property>
    </bean>  
</beans>
<p class="indent">

测试过程

public class testTransaction {	
	public static void main(String[] args) {
		ApplicationContext context =
			new ClassPathXmlApplicationContext("bean.xml");
		IService service = (IService) context.getBean("service");
		int testMethod = 1;
		switch (testMethod) {
			case 1 :
				service.method1();
				break;
			case 2 :
			
<p class="indent">

输出

customers table should  not contains customer with id 1
java.lang.ArithmeticException: / by zero
	at service.imp.Service_Imp.method1(Service_Imp.java:32)
<p class="indent">


问题:
在service.method1();中出现了/ by zero异常,这个方法在事务中
为什么数据库中有customer with id 1 没有回滚 ??
我错在哪里了?请各位解释一下spring管理事务过程好么?

zgli
2005-11-25 10:47
问题解决了

结果就是两行行代码的问题

使用spring管理DataSource事务管理,需要采用一个特定的编码规范。需要以一个特殊的方式获得连接资源或者会话资源,允许相关的 PlatformTransactionManager实现跟踪连接的使用,并且当需要时应用事务管理。
不应该调用一个数据源的 getConnection()方法和Connection的close()方法,而必须使用Spring的 org.springframework.jdbc.datasource.DataSourceUtils类,如下:
Connection conn = DataSourceUtils.getConnection(dataSource);
.......................
DataSourceUtils.releaseConnection(conn, dataSource);

我就是调用了Connection conn = dataSource.getConnection();
................................
conn.close();
结果郁闷了两天,一行代码一天

猜你喜欢