Spring事物处理规则:
运行时异常,默认回滚。
编译异常,默认提交。
事物案例:购买股票
数据库脚本
/* SQLyog v10.2 MySQL - 5.6.24 : Database - y2167 ********************************************************************* */ /*!40101 SET NAMES utf8 */; /*!40101 SET SQL_MODE=''*/; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; CREATE DATABASE /*!32312 IF NOT EXISTS*/`y2167` /*!40100 DEFAULT CHARACTER SET utf8 */; USE `y2167`; /*Table structure for table `account` */ DROP TABLE IF EXISTS `account`; CREATE TABLE `account` ( `aid` INT(11) NOT NULL AUTO_INCREMENT, `aname` VARCHAR(20) DEFAULT NULL, `balance` INT(11) DEFAULT NULL, PRIMARY KEY (`aid`) ) ENGINE=INNODB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; /*Data for the table `account` */ insert into `account`(`aid`,`aname`,`balance`) values (1,'xcq',60000); /*Table structure for table `stock` */ DROP TABLE IF EXISTS `stock`; CREATE TABLE `stock` ( `sid` int(11) NOT NULL AUTO_INCREMENT, `sname` varchar(30) DEFAULT NULL, `count` int(11) DEFAULT NULL, PRIMARY KEY (`sid`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8; /*Data for the table `stock` */ insert into `stock`(`sid`,`sname`,`count`) values (1,'股票A',5),(2,'股票B',20),(3,'股票C',30); /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
创建DAO和Service层
//DAO层 package cn.happy.day15tx.dao; /** * Created by Administrator on 2018/3/14. */ //账户 public interface IAccountDAO { public void updateAccount(int aid,int balance,boolean isBuy); } ------------------------------------------------------------------------- public interface IStockDAO { //改变股票数量 public void updateIStock(int sid,int count,boolean isBuy); } ------------------------------------------------------------------------- //DAOImpl package cn.happy.day15tx.dao.impl; import cn.happy.day15tx.dao.IStockDAO; import org.springframework.jdbc.core.support.JdbcDaoSupport; /** * Created by Administrator on 2018/3/14. */ //卖出 public class StockDaoImpl extends JdbcDaoSupport implements IStockDAO { public void updateIStock(int sid, int count, boolean isBuy) { String sql=null; if(isBuy){ //增加股票 sql="update Stock set count=count+? where sid=?"; }else{ //卖出股票 sql="update Stock set count=count-? where sid=?"; } this.getJdbcTemplate().update(sql,count,sid); } } ------------------------------------------------------------------------- package cn.happy.day15tx.dao.impl; import cn.happy.day15tx.dao.IAccountDAO; import org.springframework.jdbc.core.support.JdbcDaoSupport; /** * Created by Administrator on 2018/3/14. */ //买入 public class AccountDaoImpl extends JdbcDaoSupport implements IAccountDAO { public void updateAccount(int aid, int balance, boolean isBuy) { String sql=null; if(isBuy){ //购买 sql="update Account set balance=balance-? where aid=?"; }else{ //卖出 sql="update Account set balance=balance+? where aid=?"; } this.getJdbcTemplate().update(sql,balance,aid); } } ------------------------------------------------------------------------ Service package cn.happy.day15tx.service; /** * Created by Administrator on 2018/3/14. */ public interface IStockService { //购买股票 public void updateStock(int aid,int balance,int sid,int count) throws Exception, Exception; } ------------------------------------------------------------------------ ServiceImpl package cn.happy.day15tx.service.impl; import cn.happy.day15tx.dao.IAccountDAO; import cn.happy.day15tx.dao.IStockDAO; import cn.happy.day15tx.service.IStockService; import com.sun.javafx.beans.annotations.Default; import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; /** * Created by Administrator on 2018/3/14. */ public class StockServiceImpl implements IStockService { //植入DAO层对象 private IAccountDAO accountDAO; private IStockDAO iStockDAO; //使用注解 @Transactional(isolation = Isolation.DEFAULT,propagation = Propagation.REQUIRED,rollbackFor = Exception.class) public void updateStock(int aid, int balance, int sid, int count) throws Exception { //创建boolean对象判断是买入true还是卖出false boolean isBuy=true; accountDAO.updateAccount(aid,balance,isBuy); //定义一个异常 if(true) throw new Exception("出错了"); iStockDAO.updateIStock(sid,count,isBuy); } public IAccountDAO getAccountDAO() { return accountDAO; } public void setAccountDAO(IAccountDAO accountDAO) { this.accountDAO = accountDAO; } public IStockDAO getiStockDAO() { return iStockDAO; } public void setiStockDAO(IStockDAO iStockDAO) { this.iStockDAO = iStockDAO; } }
-------------------------------------------------------------
entity
package cn.happy.day15tx.entity;
/**
* Created by Administrator on 2018/3/14.
*/
//购票类
public class Account {
private Integer aid;
private String aname;
private Integer balance;
public Integer getAid() {
return aid;
}
public void setAid(Integer aid) {
this.aid = aid;
}
public String getAname() {
return aname;
}
public void setAname(String aname) {
this.aname = aname;
}
public Integer getBalance() {
return balance;
}
public void setBalance(Integer balance) {
this.balance = balance;
}
}
-------------------------------------------------------
package cn.happy.day15tx.entity;
/**
* Created by Administrator on 2018/3/14.
*/
//股票类
public class Stock {
private Integer sid;
private String sname;
private Integer count;
public Integer getSid() {
return sid;
}
public void setSid(Integer sid) {
this.sid = sid;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public Integer getCount() {
return count;
}
public void setCount(Integer count) {
this.count = count;
}
}
一、配置xml文件
<!--数据源--> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean> <!--识别jdbc.properties文件--> <context:property-placeholder location="classpath:jdbc.properties"/> <!--DAO--> <bean id="StockDAO" class="cn.happy.day15tx.dao.impl.StockDaoImpl"> <property name="dataSource" ref="dataSource"/> </bean> <bean id="AccountDAO" class="cn.happy.day15tx.dao.impl.AccountDaoImpl"> <property name="dataSource" ref="dataSource"/> </bean> <!--service--> <bean id="StockService" class="cn.happy.day15tx.service.impl.StockServiceImpl"> <property name="accountDAO" ref="AccountDAO"/> <property name="iStockDAO" ref="StockDAO"/> </bean> <!--事物管理器--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!--事物控制--> <!--方案一--> <bean id="stockServiceProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <property name="transactionManager" ref="transactionManager"/> <!--需要控制的类--> <property name="target" ref="StockService"/> <property name="transactionAttributes"> <props> <!--控制的方法--> <prop key="updateStock">ISOLATION_DEFAULT,PROPAGATION_REQUIRED,-Exception</prop>
<!--
ISOLATION_DEFAULT 底层数据库默认隔离级别
PROPAGATION_REQUIRED 如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务
-Exception,设置回滚(设置异常,只要出现运行时异常就会回滚)
-->
</props>
</property>
</bean>
测试方法
package day15tx; import cn.happy.JDBCTemplate.service.BookService; import cn.happy.day15tx.service.IStockService; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import java.util.List; /** * Created by Administrator on 2018/3/3. */ public class Test20180314 { //事物 @Test public void Spring(){ ApplicationContext ctx=new ClassPathXmlApplicationContext("day15tx.xml"); IStockService service=(IStockService)ctx.getBean("stockServiceProxy"); try{ service.updateStock(1,2000,1,5); }catch (Exception e){ e.printStackTrace(); } } }
二、使用注解管理事物
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!--数据源--> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean> <!--识别jdbc.properties文件--> <context:property-placeholder location="classpath:jdbc.properties"/> <!--DAO--> <bean id="StockDAO" class="cn.happy.day15tx.dao.impl.StockDaoImpl"> <property name="dataSource" ref="dataSource"/> </bean> <bean id="AccountDAO" class="cn.happy.day15tx.dao.impl.AccountDaoImpl"> <property name="dataSource" ref="dataSource"/> </bean> <!--service--> <bean id="StockService" class="cn.happy.day15tx.service.impl.StockServiceImpl"> <property name="accountDAO" ref="AccountDAO"/> <property name="iStockDAO" ref="StockDAO"/> </bean> <!--事物管理器--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!--方案二:使用注解管理事物--> <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven> </beans>
在需要管理的方法上添加注解
@Transactional(isolation = Isolation.DEFAULT,propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
三、使用AspectJ实现事物管理
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!--数据源--> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean> <!--识别jdbc.properties文件--> <context:property-placeholder location="classpath:jdbc.properties"/> <!--DAO--> <bean id="StockDAO" class="cn.happy.day15tx.dao.impl.StockDaoImpl"> <property name="dataSource" ref="dataSource"/> </bean> <bean id="AccountDAO" class="cn.happy.day15tx.dao.impl.AccountDaoImpl"> <property name="dataSource" ref="dataSource"/> </bean> <!--service--> <bean id="StockService" class="cn.happy.day15tx.service.impl.StockServiceImpl"> <property name="accountDAO" ref="AccountDAO"/> <property name="iStockDAO" ref="StockDAO"/> </bean> <!--事物管理器--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!--方案三:使用aspectJ AOP实现事物管理--> <!-- <tx:advice id="advice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="updateStock" isolation="DEFAULT" rollback-for="Exception"/> </tx:attributes> </tx:advice> <aop:config> <!–切点–> <aop:pointcut id="mypoint" expression="execution(* *..day15tx.service.*.*(..))"></aop:pointcut> <!–顾问–> <aop:advisor advice-ref="advice" pointcut-ref="mypoint"></aop:advisor> </aop:config>--> </beans>