spring2.0事务处理
spring的事务管理,实际上是将jdbc操作的繁琐代码做成了切面.
引言:传统的jdbc编程的缺点:
如:使用jdbc完成插入一条记录
1 |
代码1 ...// 核心业务代码 psmt.executeUpdate(sql) ;// 代码2 |
如上所示,为了执行一条SQL语句,我们写了许多的繁锁的代码(代码1,代码2),但这是jdbc编程所必须的,
spring的事务处理就是 : 将{代码1}和{代码2}做成了切面,开发人员只要写和业务逻辑相关的代码即可,
图片如下所示:
1. Spring提供了两种事务处理方式
(1) 编程式的
(2) 声明式的(基于Spring的AOP原理)
这里推荐使用第二种方式,因为这样可以使业务层和spring最小程度的耦合
2. 下面以添加用户为例来分别演示两种方式操作事务
3. 新建一个项目,导入以下jar包: commons-logging.jar , log4j-1.2.14.jar , spring.jar, mysql-connector-java-3.1.14-bin.jar
4. 使用编程式事务处理:
(1) 新建一个POJO类:User.java
(2) 创建操作user的接口和实现类: IUserDAO.java , UserDAOImpl2.java
(3) 编写spring配置文件applicationContext.xml
(4) 编写测试类:Test2.java
(5) 运行结果:
(1) 新建一个POJO类:User.java
////////////////////////////////////////////////////////////////////////////////////////////////////////////// package cn.koma.business.pojo; import java.io.Serializable; public class User implements Serializable { private static final long serialVersionUID = 8777636556392100355L; private Long id; private String username; private String password; public User() { super(); } public User(Long id) { super(); this.id = id; } // setter && getter }
(2) 创建操作user的接口和实现类: IUserDAO.java , UserDAOImpl2.java
package cn.koma.business.dao; import cn.koma.business.pojo.User; /** * * @author Administrator * 业务逻辑层:操作user */ public interface IUserDAO { public User addUser(User user) ; }
1 |
////////////////////////////////////////////////////////////////////////////////////////////////////////////// package cn.koma.business.dao; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.TransactionCallback; import org.springframework.transaction.support.TransactionTemplate; import cn.koma.business.pojo.User; public class UserDAOImpl2 implements IUserDAO { // 事务管理者 private PlatformTransactionManager transactionManger; // 被spring容器注入 private JdbcTemplate jdbcTemplate; public JdbcTemplate getJdbcTemplate() { return jdbcTemplate; } public void setJdbcTemplate(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } public User addUser(final User user) { // 1.simple data check if (!this.simpleCheck(user)) return null; User result = null; // 3.call jdbcTemplate to insert // (1)get the DefintionTransaction TransactionTemplate transactionTemplate = new TransactionTemplate( this.transactionManger); // (2)begin transaction result = (User) transactionTemplate.execute(new TransactionCallback() { public Object doInTransaction(TransactionStatus status) { String sql = "insert into user (username , password) values(?,?)"; // update db jdbcTemplate.update(sql, new Object[] { user.getUsername(), user.getPassword() }); // query id sql = "select max(id) from user"; Long id = jdbcTemplate.queryForLong(sql); user.setId(id); return user; } }); // 5.return result return result; } // simple data check private boolean simpleCheck(User user) { if (user == null) return false; String username = user.getUsername(); String password = user.getPassword(); if (username == null || "".equals(username)) return false; if (password == null || "".equals(password)) return false; return true; } public PlatformTransactionManager getTransactionManger() { return transactionManger; } public void setTransactionManger( PlatformTransactionManager transactionManger) { this.transactionManger = transactionManger; } } |
(3) 编写spring配置文件applicationContext.xml
1 |
////////////////////////////////////////////////////////////////////////////////////////////////////////////// <?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"> <property name="driverClassName"> <value>com.mysql.jdbc.Driver</value> </property> <property name="url"> <value>jdbc:mysql://192.168.1.196:3306/test</value> </property> <property name="username"> <value>root</value> </property> <property name="password"> <value>123456</value> </property> </bean> <!-- 配置PlatformTransactionManager --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource"> <ref bean="dataSource" /> </property> </bean> <!-- 配置jdbcTemplate --> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource"> <ref bean="dataSource" /> </property> </bean> <!-- 采用编程式事务处理 --> <bean id="userDAO2" class="cn.koma.business.dao.UserDAOImpl2"> <property name="jdbcTemplate"> <ref bean="jdbcTemplate" /> </property> <property name="transactionManger"> <ref bean="transactionManager" /> </property> </bean> </beans> |
(4) 编写测试类:Test2.java
1 |
////////////////////////////////////////////////////////////////////////////////////////////////////////////// package cn.koma.test; import org.springframework.beans.factory.BeanFactory; import org.springframework.context.support.FileSystemXmlApplicationContext; import cn.koma.business.dao.IUserDAO; import cn.koma.business.pojo.User; public class Test2 { public static void main(String[] args) { // 1.加载spring配置文件 BeanFactory factory = new FileSystemXmlApplicationContext( "applicationContext.xml"); // 2.得到userDAO实例 IUserDAO userDAO = (IUserDAO) factory.getBean("userDAO2"); // 3.调用userDAO添加user User user = new User(); user.setUsername("koma2"); user.setPassword("123456"); user = userDAO.addUser(user); if (user == null) return; System.out.println("id : " + user.getId()); System.out.println("username : " + user.getUsername()); System.out.println("password : " + user.getPassword()); } } |
(5) 运行结果:
1 |
////////////////////////////////////////////////////////////////////////////////////////////////////////////// id : 4 username : koma2 password : 123456 |
5. 使用声明式事务处理:
(1) 新建一个POJO类:User.java
代码同上
(2) 创建操作user的接口和实现类: IUserDAO.java , UserDAOImpl.java
IUserDAO.java代码同上
1 |
////////////////////////////////////////////////////////////////////////////////////////////////////////////// package cn.koma.business.dao; import org.springframework.jdbc.core.JdbcTemplate; import cn.koma.business.pojo.User; public class UserDAOImpl implements IUserDAO { // 被spring容器注入 private JdbcTemplate jdbcTemplate; public JdbcTemplate getJdbcTemplate() { return jdbcTemplate; } public void setJdbcTemplate(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } public User addUser(User user) { // 1.simple data check if (!this.simpleCheck(user)) return null; // 2.create sql String username = user.getUsername(); String password = user.getPassword(); String sql = "insert into user (username , password) values(?,?)"; // 3.call jdbcTemplate to insert this.jdbcTemplate.update(sql, new Object[] { username, password }); // 4.query the id sql = "select max(id) from user"; Long id = jdbcTemplate.queryForLong(sql); user.setId(id); // 5.return result return user; } // simple data check private boolean simpleCheck(User user) { if (user == null) return false; String username = user.getUsername(); String password = user.getPassword(); if (username == null || "".equals(username)) return false; if (password == null || "".equals(password)) return false; return true; } } |
(3) 编写spring配置文件applicationContext.xml
1 |
////////////////////////////////////////////////////////////////////////////////////////////////////////////// <?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"> <property name="driverClassName"> <value>com.mysql.jdbc.Driver</value> </property> <property name="url"> <value>jdbc:mysql://192.168.1.196:3306/test</value> </property> <property name="username"> <value>root</value> </property> <property name="password"> <value>123456</value> </property> </bean> <!-- 配置PlatformTransactionManager --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource"> <ref bean="dataSource" /> </property> </bean> <!-- 配置jdbcTemplate --> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource"> <ref bean="dataSource" /> </property> </bean> <!-- 配置userDAO --> <!-- 采用声明式事务处理 --> <bean id="userDAO" class="cn.koma.business.dao.UserDAOImpl"> <property name="jdbcTemplate"> <ref bean="jdbcTemplate" /> </property> </bean> <!-- 使用代理,外界只要知道它就行了 --> <bean id="userDAOProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <property name="transactionManager"> <ref bean="transactionManager" /> </property> <!-- 设置事务的属性定义 --> <property name="transactionAttributes"> <props> <prop key="add*">PROPAGATION_REQUIRED</prop> </props> </property> <!-- 配置代理目标 --> <property name="target"> <ref bean="userDAO" /> </property> </bean> </beans> |
关于spring事务属性的配置,可以参考这篇文章:http://klyuan.javaeye.com/blog/78674?page=3
(4) 编写测试类:Test.java
1 |
////////////////////////////////////////////////////////////////////////////////////////////////////////////// package cn.koma.test; import org.springframework.beans.factory.BeanFactory; import org.springframework.context.support.FileSystemXmlApplicationContext; import cn.koma.business.dao.IUserDAO; import cn.koma.business.pojo.User; public class Test { public static void main(String[] args) { // 1.加载spring配置文件 BeanFactory factory = new FileSystemXmlApplicationContext( "applicationContext.xml"); // 2.得到userDAO实例 IUserDAO userDAO = (IUserDAO) factory.getBean("userDAOProxy"); // 3.调用userDAO添加user User user = new User(); user.setUsername("koma"); user.setPassword("123456"); user = userDAO.addUser(user); if (user == null) return; System.out.println("id : " + user.getId()); System.out.println("username : " + user.getUsername()); System.out.println("password : " + user.getPassword()); } } |
(5) 运行结果:
1 |
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
id : 5
username : koma1
password : 123456 |
6. 可以看出 , 使用声明式事务处理 , 让我们的代码可以尽量少的与spring耦合
7. spring在jdk5.0之后,支持@AspectJ,可以使用注解来配置事务,读者可以参考相关文章