三明市建设局网站官网,旅游开发公司网站建设方案书,wordpress 选项卡,tk网站免费1.事务介绍
1.1什么是事务#xff1f;
当你需要一次执行多条SQL语句时#xff0c;可以使用事务。通俗一点说#xff0c;如果这几条SQL语句全部执行成功#xff0c;则才对数据库进行一次更新#xff0c;如果有一条SQL语句执行失败#xff0c;则这几条SQL语句全部不进行执…1.事务介绍
1.1什么是事务
当你需要一次执行多条SQL语句时可以使用事务。通俗一点说如果这几条SQL语句全部执行成功则才对数据库进行一次更新如果有一条SQL语句执行失败则这几条SQL语句全部不进行执行这个时候需要用到事务。
回顾一下数据库事务的四大特性ACID
原子性Atomicity 要么都执行要么都不执行
一致性Consistency 事务前后的数据都是正确的
隔离性Isolation 事物之间相互隔离互不干扰并发执行的事务彼此无法看到对方的中间状态
持久性Durability 事务一旦提交不可再回滚 1.2数据库本身控制事物
begin transaction//1.本地数据库操作张三减少金额//2.本地数据库操作李四增加金额
rollback;
或
commit transation; 1.3jdbc中使用事物
1.获取对数据库的连接
2.设置事务不自动提交默认情况是自动提交的
conn.setAutoCommit(false); //其中conn是第一步获取的随数据库的连接对象。 3.把想要一次性提交的几个sql语句用事务进行提交
try{Statement stmt null; stmt conn.createStatement(); stmt.executeUpdate(sql1); int a6/0;stmt.executeUpdate(Sql2); . . . conn.commit(); //使用commit提交事务
}
4.捕获异常进行数据的回滚回滚一般写在catch块中
catchException e { ... conn.rollback();
}
2.转账案例
2.1创建工程 2.2添加转账业务 2.2.1mapper
package com.by.mapper;import com.by.pojo.User;
import org.apache.ibatis.annotations.Param;public interface UserMapper {public void addUser(User user);void updateUserOutMoney(Param(source) String source, Param(money)float money);void updateUserInMoney(Param(target) String target, Param(money)float money);
}xml
?xml version1.0 encodingUTF-8 ?
!DOCTYPE mapperPUBLIC -//mybatis.org//DTD Mapper 3.0//ENhttp://mybatis.org/dtd/mybatis-3-mapper.dtd
mapper namespacecom.by.mapper.UserMapperinsert idaddUser parameterTypecom.by.pojo.Userinsert into t_user(name,money) values(#{name},#{money})/insertupdate idupdateUserOutMoneyupdate t_user set moneymoney-#{money} where name#{source}/updateupdate idupdateUserInMoney update t_user set moneymoney#{money} where name#{target}/update
/mapper
2.2.2service
package com.by.service;import com.by.mapper.UserMapper;
import com.by.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;Service
public class UserServiceImpl implements UserService{Autowiredprivate UserMapper userMapper;Overridepublic void addUser(User user){userMapper.addUser(user);}Overridepublic void updateUser(String source, String target, Float money) {userMapper.updateUserOutMoney(source,money);
userMapper.updateUserInMoney(target,money);}}2.2.3测试
package com.by.web;import com.by.pojo.User;
import com.by.service.UserService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;import javax.annotation.Resource;RunWith(SpringJUnit4ClassRunner.class)//加载配置文件
ContextConfiguration(classpath:applicationContext.xml)
public class Client {Autowired
// Resource(name proxyUserService)
//Qualifier(proxyUserService)private UserService userService;Testpublic void addUser(){userService.addUser(new User(小龙女,4000F));userService.addUser(new User (李莫愁,2000F));
}Test
public void testUpdateUser(){userService.updateUser(张三丰,宋远桥,1F);
}
}
2.2.4结果 1.此时我们观察数据表里面的变化情况 转账是成功的但是涉及到业务的问题如果业务层实现类有其中一个环节出问题都会导致灾难。
2.我们先把数据恢复到转账前。 现在我们故意模拟转账业务出现问题 Overridepublic void updateUser(String source, String target, Float money) {
//转出userMapper.updateUserOutMoney(source,money);//制造转账异常int a6/0;//转入userMapper.updateUserInMoney(target,money);
} 再来测试 业务执行出错但是 这是因为不满足事务的一致性减钱的事务提交了加钱的事务没有提交甚至都没有执行到。
3.Spring中事务控制的API介绍 说明 JavaEE体系进行分层开发事务处理位于业务层Spring提供了分层设计业务层的事务处理解决方案。 Spring框架为我们提供了一组事务控制的接口。具体在后面的小节介绍。这组接口是在spring-tx.RELEASE.jar中。 spring的事务控制都是基于AOP的它既可以使用编程的方式实现也可以使用配置的方式实现。我们学习的重点是使用配置的方式实现。
3.1PlatformTransactionManager 此接口是spring的事务管理器它里面提供了我们常用的操作事务的方法源代码如下
public interface PlatformTransactionManager { //开启事务 TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException; //提交事务void commit(TransactionStatus status) throws TransactionException; //回滚事务void rollback(TransactionStatus status) throws TransactionException;
} 真正管理事务的对象: Spring为不同的orm框架提供了不同的PlatformTransactionManager接口实现类 DataSourceTransactionManager使用Spring JDBC或iBatis 进行持久化数据时使用 HibernateTransactionManager使用Hibernate版本进行持久化数据时使用
3.2TransactionDefinition TransactionDefinition接口包含与事务属性相关的方法源代码如下
public interface TransactionDefinition {int PROPAGATION_REQUIRED 0;int PROPAGATION_SUPPORTS 1;int PROPAGATION_MANDATORY 2;int PROPAGATION_REQUIRES_NEW 3;int PROPAGATION_NOT_SUPPORTED 4;int PROPAGATION_NEVER 5;int PROPAGATION_NESTED 6;int ISOLATION_DEFAULT -1;int ISOLATION_READ_UNCOMMITTED 1;int ISOLATION_READ_COMMITTED 2;int ISOLATION_REPEATABLE_READ 4;int ISOLATION_SERIALIZABLE 8;int TIMEOUT_DEFAULT -1;//传播行为int getPropagationBehavior();//隔离级别int getIsolationLevel();//事务超时int getTimeout();//是否只读boolean isReadOnly();
}TransactionDefinition 接口定义的事务规则包括事务隔离级别、事务传播行为、事务超时、事务的只读、回滚规则属性同时Spring 还为我们提供了一个默认的实现类DefaultTransactionDefinition该类适用于大多数情况。如果该类不能满足需求可以通过实现 TransactionDefinition 接口来实现自己的事务定义。
3.2.1事务隔离级别 事务并发时的安全问题 问题描述隔离级别脏读一个事务读取到另一个事务还未提交的数据read-commited不可重复读一个事务内多次读取一行数据的内容其结果不一致repeatable-read幻读一个事务内多次读取一张表中的内容其结果不一致serialized-readSpring事务隔离级别比数据库事务隔离级别多一个default由低到高为 隔离级别ISOLATION_DEFAULT这是一个platfromtransactionmanager默认的隔离级别使用数据库默认的事务隔离级别。ISOLATION_READ_UNCOMMITTED这是事务最低的隔离级别会产生脏读不可重复读和幻像读。ISOLATION_READ_COMMITTED这种事务隔离级别可以避免脏读出现但是可能会出现不可重复读和幻像读。 Oracle数据库默认的隔离级别。ISOLATION_REPEATABLE_READ这种事务隔离级别可以防止脏读、不可重复读但是可能出现幻像读。MySQL数据库默认的隔离级别。ISOLATION_SERIALIZABLE这是花费最高代价但是最可靠的事务隔离级别事务被处理为顺序执行。除了防止脏读、不可重复读外还避免了幻像读。3.2.2事务的传播行为 什么是事务传播行为 事务传播行为propagation behavior指的就是当一个事务方法被另一个事务方法调用时这个事务方法应该如何进行。 例如methodA事务方法调用methodB事务方法时methodB是继续在调用者methodA的事务中运行呢还是为自己开启一个新事务运行这就是由methodB的事务传播行为决定的。 Spring定义了七种传播行为 事务传播行为类型说明PROPAGATION_REQUIRED如果当前没有事务就新建一个事务如果已经存在一个事务中加入到这个事务中。这是最常见的选择。PROPAGATION_SUPPORTS支持当前事务如果当前没有事务就以非事务方式执行。PROPAGATION_MANDATORY使用当前的事务如果当前没有事务就抛出异常。PROPAGATION_REQUIRES_NEW新建事务如果当前存在事务把当前事务挂起。PROPAGATION_NOT_SUPPORTED以非事务方式执行操作如果当前存在事务就把当前事务挂起。PROPAGATION_NEVER以非事务方式执行如果当前存在事务则抛出异常。PROPAGATION_NESTED如果当前存在事务则在嵌套事务内执行。如果当前没有事务则执行与REQUIRED类似的操作。
3.2.3事务超时 timeout事务超时时间 当前事务所需操作的数据被其他事务占用则等待。 100自定义等待时间100秒。 -1由数据库指定等待时间默认值。建议
3.2.4读写性 readonly 读写性 true只读可提高查询效率适合查询 false可读可写适合增删改
3.2.5回滚规则
TransactionAttributeTransactionAttribute 的默认实现类是DefaultTransactionAttribute 它同时继承了DefaultTransactionDefinition。在DefaultTransactionDefinition 的基础上增加了rollbackOn的实现DefaultTransactionAttribute的实现指定了当异常类型为unchecked exception 的情况下将回滚事务。 rollbackOn 回滚规则可省略或设置 rollbackOnException 如果事务中抛出 RuntimeException,则自动回滚 如果事务中抛出 CheckException不会自动回滚
3.3TransactionStatus PlatformTransactionManager.getTransaction(…) 方法返回一个 TransactionStatus 对象该对象代表一个新的或已经存在的事务源代码如下
public interface TransactionStatus{boolean isNewTransaction();void setRollbackOnly();boolean isRollbackOnly();
} 4.改造转账案例
4.1applicationContext.xml
!-- 事务管理器DataSourceTransactionManager:负责开启、提交、回滚事务--bean idtransactionManager classorg.springframework.jdbc.datasource.DataSourceTransactionManagerproperty namedataSource refdataSource/property/bean
-- 事务属性DefaultTransactionDefinition:配置事务的属性--bean idtransactionDefinition classorg.springframework.transaction.support.DefaultTransactionDefinition
!-- isolationLevel:控制事务的隔离性有默认值默认值为DEFAULTpropagationBehavior:事务的传播行为有默认值默认值为REQUIREDreadOnly:只读性有默认值默认值为falsetimeout:事务超时有默认值默认永不超时--property nameisolationLevelName valueDEFAULT/propertyproperty namepropagationBehaviorName valueREQUIRED/propertyproperty namereadOnly valuefalse/propertyproperty nametimeout value-1/property/bean 4.2service
Service
public class UserServiceImpl implements UserService {Autowiredprivate UserMapper userMapper;Autowiredprivate TransactionDefinition txDefinition;Autowiredprivate PlatformTransactionManager txManager;/*** 转账* param source* param target* param money*/Overridepublic void updateUser(String source, String target, Float money) {// 获取一个事务TransactionStatus txStatus txManager.getTransaction(txDefinition);try {userMapper.updateUserOfSub(source, money);int a 6/0;userMapper.updateUserOfAdd(target, money);//提交事务txManager.commit(txStatus);}catch (Exception e){//回滚事务txManager.rollback(txStatus);e.printStackTrace();}}
} 4.3测试
RunWith(SpringJUnit4ClassRunner.class)
ContextConfiguration(classpath:applicationContext.xml)//加载配置文件
public class ServiceTest {Autowiredprivate UserService userService;/*** 转账业务*/Testpublic void testUpdate(){userService.updateUser(张三丰,宋远桥,1F);}
} 事务回滚 满足执行 我们现在虽然实现了事务控制但是代码非常的臃肿我们可以使用动态代理简化代码
5.动态代理控制事务 5.1factory
我们创建一个工厂专门用来给 Service 创建代理对象如下
package com.by.factory;import com.by.service.UserService;
import com.by.service.UserServiceImpl;
import org.hamcrest.Factory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;/*** bean工厂*/
Component
public class BeanFactory {Autowiredprivate UserService userService;Autowiredprivate TransactionDefinition txDefinition;Autowiredprivate PlatformTransactionManager txManager;/*** 获得UserServiceImpl对象** return*/public UserService getUserService() {return (UserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(),userService.getClass().getInterfaces(),new InvocationHandler() {public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {//开启事务TransactionStatus txStatus txManager.getTransaction(txDefinition);try {method.invoke(userService, args);//提交事务txManager.commit(txStatus);} catch (Exception e) {//回滚事务txManager.rollback(txStatus);e.printStackTrace();}return null;}});}
} 5.2applicationContext.xml
!-- 注入工厂生成代理UserService--bean idproxyUserService factory-beanbeanFactory factory-methodgetUserService/bean 5.3service
Service
public class UserServiceImpl implements UserService {Autowiredprivate UserMapper userMapper;/*** 转账* param source* param target* param money*/Overridepublic void updateUser(String source, String target, Float money) {userMapper.updateUserOfSub(source, money);int a 6/0;userMapper.updateUserOfAdd(target, money);}
} 5.4测试
RunWith(SpringJUnit4ClassRunner.class)
ContextConfiguration(classpath:applicationContext.xml)
public class ServiceTest {AutowiredQualifier(proxyService)//注入代理对象private UserService userService;Testpublic void testUpdate(){userService.updateUser(张三丰,宋远桥,1F);}
} 事务回滚 6.Spring AOP控制事务
6.1导入schema约束
?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:contexthttp://www.springframework.org/schema/contextxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:txhttp://www.springframework.org/schema/tx xmlns:aophttp://www.springframework.org/schema/aopxsi:schemaLocationhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsdhttp://www.springframework.org/schema/aophttps://www.springframework.org/schema/aop/spring-aop.xsd
/beans 6.2配置增强、切点、切面
!-- 增强要做的事情。eg:日志、事务--tx:advice idtxManager transaction-managertransactionManager!-- 定义属性--tx:attributestx:method nameget* propagationSUPPORTS read-onlytrue/tx:method nameselect* propagationSUPPORTS read-onlytrue/tx:method name* //tx:attributes/tx:adviceaop:config!-- 切点:实际要增强的方法--aop:pointcut idpointcut expressionexecution(* com.by.service.*.*(..))/!-- 切面:将增强作用与切点上--aop:advisor advice-reftxManager pointcut-refpointcut/aop:advisor/aop:config6.3测试
package com.by.web;import com.by.pojo.User;
import com.by.service.UserService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;import javax.annotation.Resource;RunWith(SpringJUnit4ClassRunner.class)//加载配置文件
ContextConfiguration(classpath:applicationContext.xml)
public class Client {Autowired
// Resource(name proxyUserService)
//Qualifier(proxyUserService)private UserService userService;Testpublic void addUser(){userService.addUser(new User(小龙女,4000F));userService.addUser(new User (李莫愁,2000F));
}Test
public void testUpdateUser(){userService.updateUser(张三丰,宋远桥,1F);
}
}事务回滚 7.基于注解的AOP控制事务
7.1applicationContext.xml
!-- 开启spring对注解事务的支持 --
tx:annotation-driven transaction-managertransactionManager/ 7.2service
package com.by.service;import com.by.mapper.UserMapper;
import com.by.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.DefaultTransactionDefinition;Service
public class UserServiceImpl implements UserService{Autowiredprivate UserMapper userMapper;Overridepublic void addUser(User user){userMapper.addUser(user);}Transactional(isolation Isolation.DEFAULT,propagation Propagation.REQUIRED,timeout -1,readOnly false,rollbackFor Exception.class)Overridepublic void updateUser(String source, String target, Float money) {userMapper.updateUserOutMoney(source,money);//制造转账异常int a6/0;//转入userMapper.updateUserInMoney(target,money);}}
7.3测试 package com.by.web;import com.by.pojo.User;
import com.by.service.UserService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;import javax.annotation.Resource;RunWith(SpringJUnit4ClassRunner.class)//加载配置文件
ContextConfiguration(classpath:applicationContext.xml)
public class Client {Autowired
// Resource(name proxyUserService)
//Qualifier(proxyUserService)private UserService userService;Testpublic void addUser(){userService.addUser(new User(小龙女,4000F));userService.addUser(new User (李莫愁,2000F));
}Test
public void testUpdateUser(){userService.updateUser(张三丰,宋远桥,1F);
}
}事务回滚 8.总结
spring事务控制 1、事务介绍 1什么是事务 执行多条sql要么全部执行要么全部回滚 2事务的特点 原子性事务是最小执行单位 一致性事务前后数据都是正确的 隔离性事务之间看不到彼此的中间状态 持久性事务一旦提交不可再回滚 3mysql控制事务 START TRANSACTION; sql1; sql2; COMMIT 或 ROLLBACK; 4jdbc控制事务 try{ conn.setAutoCommit(false); .... conn.commit(); }catch(Exception e){ conn.rollback(); } spring事务控制的api 1、PlatformTransactionManager 作用是一个事务管理器负责开启、提交或回滚事务 实现类DataSourceTransactionManager(sqlSession) 2、TransactionDefinition 作用定义事务的属性 实现类DefaultTransactionDefinition 属性 1隔离级别【有默认值】 DEFAULT默认值等价于REPEATABLE_READ READ_UNCOMMITTED x x x READ_COMMITTED 脏读 x x REPEATABLE_READ 脏读 不可重复度 SERIALIZABLE 脏读 不可重复度 幻读 2事务的传播行为【有默认值】 REQUIRED默认值methodB()会加入到methodA()事务中 3事务超时【有默认值】 默认-1永不超时 4是否只读【有默认值】 readOnly false默认值适用于增删改 readOnly true不记录log(效率快)适用于查询 5回滚规则 可省略运行时异常回滚编译时异常不回滚 3、TransactionStatus 作用代表一个事务