【Spring】Spring之事务处理
编程式事务
/** * 1. 根据DataSource去创建事务管理器 * 构造方法 , 参数1. DataSource */ DataSourceTransactionManager txManager = new DataSourceTransactionManager(getDataSource()); /** * 2. 创建事务模版对象, 并将事务管理器传递给模版 */ TransactionTemplate ttlate = new TransactionTemplate(txManager); /** * 3. 通过事务模版 , 执行事务, 并指定事务的回调函数 */ Boolean flag = ttlate.execute(new TransactionCallback<Boolean>() { /** * 我们要处理的JDBC操作, 可以放到这个方法中, 在这个方法里的所有JDBC操作, 将视为一个事务 * * 这个方法, 如何认定事务是否应该提交 : * * 当方法中出现异常, 则表示事务执行失败 , * 如果异常进行了处理, 则事务执行成功! */ @Override public Boolean doInTransaction(TransactionStatus status) { try{ getJdbcTemplate().update("update book set bookname=? where bookid=?", "西游记",10002); if(1==2){ throw new RuntimeException("停电了, 哈哈哈"); } getJdbcTemplate().update("update book set bookname=? where bookid=?", "红楼梦",10003); return true; }catch(Exception e){ e.printStackTrace(); //处理了异常 , 没事了 //加入回滚标记 ( 本次事务不提交 ) status.setRollbackOnly(); return false; } } }); System.out.println("事务执行的结果:"+flag);
声明式事务
相较于编程式的事务 ,有利有弊 !
优点:
是一种aop的编程思想, 给一段代码添加事务, 无需修改原代码
缺点:
因为采用了注解, 注解的最小范围只能给类的成员 , 也就是说, 声明时的事务 ,最小的处理范围是一个方法 !
使用步骤:
1. 向容器中添加事务的管理对象 <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <constructor-arg index="0" ref="dataSource"></constructor-arg> </bean> 2. 开启事务的扫描 , 指定事务管理器 <tx:annotation-driven transaction-manager="txManager" proxy-target-class="true"/> 3. 在具体要被执行事务的方法上, 添加注解@Transactional即可
@Transactional也可以添加到类上,表示对该类的所有方法使用事务
@Transactional注解的属性
@Transactional注解标记有以下属性,在使用时
可以根据需要做特殊设定。
propagation: 设置事务传播
isolation : 设置事务隔离级别
readOnly : 设置为只读,还是可读写
rollbackFor : 设置遇到哪些异常必须回滚
noRollbackFor : 设置遇到哪些异常不回滚
看一个Demo:
User类:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package cn.wxg.bean; public class User { private int id; private String name; private String password; public User() { super(); } public int getId() { return id; } public User(int id, String name, String password) { super(); this.id = id; this.name = name; this.password = password; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Override public String toString() { return "User [id=" + id + ", name=" + name + ", password=" + password + "]"; } }
Dao类:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package cn.wxg.dao; import java.util.List; import org.springframework.jdbc.core.support.JdbcDaoSupport; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.support.TransactionCallback; import org.springframework.transaction.support.TransactionTemplate; import cn.wxg.bean.User; public class UserDao extends JdbcDaoSupport { @Transactional public void test2(List<User> user){ String sql1="update test_user set password=? where name=?"; String sql2="update test_user set password=? where name=?"; getJdbcTemplate().update(sql1, user.get(0).getPassword(),user.get(0).getName()); getJdbcTemplate().update(sql2, user.get(1).getPassword(),user.get(1).getName()); } public boolean updateUser(List<User> user){ String sql1="update test_user set password=? where name=?"; String sql2="update test_user set password=? where name=?"; //声明事务管理组件 DataSourceTransactionManager dstt = new DataSourceTransactionManager(getDataSource()); //声明事务组件 TransactionTemplate tt = new TransactionTemplate(dstt); //执行事务 Boolean res = tt.execute(new TransactionCallback<Boolean>(){ @Override public Boolean doInTransaction(TransactionStatus status){ try{ getJdbcTemplate().update(sql1, user.get(0).getPassword(),user.get(0).getName()); getJdbcTemplate().update(sql2, user.get(1).getPassword(),user.get(1).getName()); return true; }catch(Exception e){ status.setRollbackOnly();//回滚 } return false; } }); return res; } }
XML文件:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?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:jdbc="http://www.springframework.org/schema/jdbc" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:util="http://www.springframework.org/schema/util" xmlns:jpa="http://www.springframework.org/schema/data/jpa" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.1.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.1.xsd"> <bean id="database" class="org.apache.commons.dbcp.BasicDataSource"> <!-- 驱动地址 --> <property name="driverClassName" value="oracle.jdbc.OracleDriver"></property> <!-- 数据库的连接地址 --> <property name="url" value="jdbc:oracle:thin:@localhost:1521:xe"></property> <!-- 数据库的帐号 --> <property name="username" value="system"></property> <!-- 数据库的密码 --> <property name="password" value="517839"></property> </bean> <bean id="userDao" class="cn.wxg.dao.UserDao"> <!-- 在调用set方法进行赋值, Spring容器是通过反射技术 ,根据我们传递的name参数 , 得到对应的set方法名称, 将其调用 --> <property name="dataSource" ref="database"></property> </bean> <!--配置DataSourceTransactionManager,事务管理着对象|--> <bean id="txManage" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <constructor-arg index="0" ref="database"></constructor-arg> </bean> <!--开启事务扫描--> <tx:annotation-driven transaction-manager="txManage" proxy-target-class="true"/> <!--文件扫描--> <context:component-scan base-package="cn"></context:component-scan> </beans>
测试类:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package cn.wxg.text; import java.util.ArrayList; import java.util.List; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import cn.wxg.bean.User; import cn.wxg.dao.UserDao; public class UserDaoTest { @Test public void testName1() throws Exception { //加载配置文件 ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml"); UserDao userDao = ac.getBean("userDao", UserDao.class); User user1=new User(1001,"jame","987654321"); User user2=new User(1002,"locy","987654321"); List<User> users=new ArrayList<User>(); users.add(user1); users.add(user2); // System.out.println(userDao.updateUser(users)); userDao.test2(users); } }