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>