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


由于问题较长,希望各位高手能够耐心看完,谢谢, 数据库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;
}

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>

测试过程


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 :


输出

customers table should not contains customer with id 1
java.lang.ArithmeticException: / by zero
at service.imp.Service_Imp.method1(Service_Imp.java:32)

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

问题解决了

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

使用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();
结果郁闷了两天,一行代码一天