Spring提供了一致的事务管理抽象。这个抽象是Spring最重要的抽象之一, 它有如下的优点:
1.为不同的事务API提供一致的编程模型,如JTA、JDBC、Hibernate、iBATIS数据库层 和JDO
2.提供比大多数事务API更简单的,易于使用的编程式事务管理API
3.整合Spring数据访问抽象
4.支持Spring声明式事务管理
环境:eclipse3.0,JDK1.4,spring1.2.3,mysql
程序主体代码如下:
配置文件:
<?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.springframework.jdbc.datasource.DriverManagerDataSource" destroy-method="close"> <property name="driverClassName"> <value>com.mysql.jdbc.Driver</value> </property> <property name="url"> <value>jdbc:mysql://localhost:3306/test</value> </property> <property name="username"> <value>root</value> </property> <property name="password"> <value>1234</value> </property> </bean> <bean id="business" class="databaserollback.BusinessImpl"> <property name="dataSource"> <ref bean="dataSource"/> </property> </bean> <bean id="dbTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource"> <ref bean="dataSource"/> </property> </bean> <bean id="accountservice" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" > <property name="transactionManager" ><ref bean="dbTransactionManager" /></property> <property name="target"> <ref bean="business" /> </property> <property name="transactionAttributes" > <props> <prop key="insertOne">PROPAGATION_REQUIRED</prop> </props> </property> </bean> </beans> |
业务类:
public class BusinessImpl implements Business { DataSource
dataSource = null; /** * @throws SQLException *
*/ public void insertOne() { Connection conn =
DataSourceUtils.getConnection(dataSource); Statement stat;
try { stat = conn.createStatement();
String sql = "insert into room1 (room_id,address) values
('1','dalian')"; String sql1 = "insert into room1 (room_id,address)
values ('1','dalian')";
stat.executeUpdate(sql); stat.executeUpdate(sql1); } catch (SQLException e) {
}
System.out.println("insertOne"); } /** * @return Returns the ds. */ public DataSource
getDataSource() { return dataSource; } /** *
@param ds The ds to set. */ public void setDataSource(DataSource
dataSource) { this.dataSource = dataSource; } }
|
测试类:
public class Test { protected static PlatformTransactionManager transactionManager; protected static TransactionStatus transactionStatus; public static void main(String[] args) throws SQLException { ClassPathResource res; XmlBeanFactory factory; res = new ClassPathResource("Appcontext.xml"); factory = new XmlBeanFactory(res); //transactionManager = (PlatformTransactionManager) factory.getBean("dbTransactionManager"); //transactionStatus = transactionManager.getTransaction(new DefaultTransactionDefinition()); Business bi = (Business) factory.getBean("accountservice"); // // try { bi.insertOne();
// } catch (SQLException e) { // transactionManager.rollback(transactionStatus); // } } }
|
因为使用的数据库是mysql,所以建立表的时候要指定INNODB,来支持事务!
CREATE TABLE room1 (
ROOM_ID varchar(10),
ADDRESS varchar(32),
PRIMARY KEY (ROOM_ID)
) TYPE=INNODB;
执行这段代码之后,控制台抛出错误,查询数据库,发现事务没有回滚,为什么呢??
首先要了解spring处理事务的本质,只有当程序抛出一个RuntimeException-->DataAccessException是spring才会捕获他,并且进行事务的处理!
我们将上面的业务类修改一下,使用spring封装的JDBCTemplate
JdbcTemplate jt = new JdbcTemplate(dataSource);
jt.update("insert into room1 (room_id,address) values ('1','dalian')");
jt.update("insert into room1 (room_id,address) values ('1','dalian')");
重新运行代码,发现数据库成功回滚!但是spring的template虽然很方便,但是对JDBC的支持还是不够完善,所以很多人还是喜欢用原生的JDBC来操作数据库,根据spring对事务操作的特点,我们对程序中抛出的SQLException坐一下改造
catch (SQLException e) { throw new MyUncheckException(e.toString()); } public class MyUncheckException extends DataAccessException { /** * @param msg */ public MyUncheckException(String msg) { super(msg); // TODO Auto-generated constructor stub } }
|