范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

Spring系列教程五一文了解Spring事务

  数据库事务(Database Transaction)是指将一系列数据库操作当作一个逻辑处理单元的操作,这个单元中的数据库操作要么完全执行,要么完全不执行。通过将一组相关操作组合为一个逻辑处理单元,可以简化错误恢复,并使应用程序更加可靠。5.1 事务的特性
  一个逻辑处理单元要成为事务,必须满足ACID(原子性、一致性、隔离性和持久性)属性。所谓的ACID含义如下。原子性(Atomicity):一个事务内的操作,要么全部执行成功,要么全部不成功。一致性(Consistency):事务执行后,数据库状态与其他业务规则保持一致。如转账业务,无论事务执行成功与否,参与转账的两个账号余额之和应该是不变的。隔离性(Isolation):每个事务独立运行。在并发环境中,并发的事务是互相隔离的,互不影响。持久性(Durability):事务一旦提交后,数据库中的数据必须被永久地保存下来。5.1 JDBC事务
  在Java基础的学习中可以知道JDBC事务通常通过Connection接口的方法来控制事务开始,事务提交以及事务回滚,下面,先通过简单的实例回顾JDBC事务。package cn.bytecollege.util;  import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException;  public class DBUtil {     //省略加载驱动步骤     public void save() throws SQLException {         String url = "jdbc:mysql://localhost:3306?chapter05";         String username = "root";         String password = "root";         Connection connection = null;         try{             connection = DriverManager.getConnection(url,username,password);             //开启事务             connection.setAutoCommit(false);             //省略新增操作             //提交事务             connection.commit();         }catch (SQLException e){             e.printStackTrace();             connection.rollback();         }     } }
  直接使用JDBC的编程方式管理事务,虽然可以完成对应的功能,但这种编程方式对代码的复用性不高。为了解决通过直接适应JDBC的方式对事务进行控制,提高代码复用性的问题,Spring也提供了对事务进行控制的相关API,下面将介绍使用Spring的方式进行事务管理。5.2 Spring事务管理
  在正式学习Spring事务管理前,需要做一些准备工作,首先准备数据库,并初始化数据CREATE DATABASE SPRING_CHAPTER05; USE SPRING_CHAPTER05; CREATE TABLE STUDENT(     STUDENT_ID INT PRIMARY KEY AUTO_INCREMENT,     STUDENT_NAME VARCHAR(20),     STUDENT_AGE TINYINT,     STUDENT_GENDER CHAR(2) ); CREATE TABLE STUDENT_INFO(     STUDENT_DETAIL_ID INT PRIMARY KEY AUTO_INCREMENT,     STUDENT_ID INT,     MAIL VARCHAR(30),     TELEPHONE VARCHAR(15) ) INSERT INTO `spring_chapter05`.`student`(`STUDENT_ID`, `STUDENT_NAME`, `STUDENT_AGE`, `STUDENT_GENDER`) VALUES (1, "张三", 19, "男"); INSERT INTO `spring_chapter05`.`student`(`STUDENT_ID`, `STUDENT_NAME`, `STUDENT_AGE`, `STUDENT_GENDER`) VALUES (2, "李四", 18, "女");  INSERT INTO `spring_chapter05`.`student_info`(`STUDENT_DETAIL_ID`, `STUDENT_ID`, `MAIL`, `TELEPHONE`) VALUES (1, 1, "zhangsan@163.com", "17765868611"); INSERT INTO `spring_chapter05`.`student_info`(`STUDENT_DETAIL_ID`, `STUDENT_ID`, `MAIL`, `TELEPHONE`) VALUES (2, 2, "lisi@163.com", "18676543421");
  为了便于操作数据库以及学习Spring事务,在本小节内整合Mybatis框架。5.2.1 Spring整合Mybatis创建Maven项目,并添加如下依赖。              junit       junit       4.11       test                      mysql       mysql-connector-java       8.0.15                      org.mybatis       mybatis       3.5.6                      org.mybatis       mybatis-spring       2.0.6                      com.alibaba       druid       1.2.6                      org.projectlombok       lombok       1.18.20       provided                 org.springframework       spring-context       5.3.9                      org.springframework       spring-tx       5.3.9                      org.springframework       spring-jdbc       5.3.9                      log4j       log4j       1.2.17        
  需要注意的是Mybatis为了同Spring整合,推出了Mybatis-Spring项目,因此需要添加该依赖,除此以外还需要添加Spring-jdbc及Spring-tx等依赖。新建cn.bytecollege.entity包,并在包中创建实体类:package cn.bytecollege.entity; import lombok.Data; @Data public class Student {     private int studentId;     private String studentName;     private int studentAge;     private String studentGender; } package cn.bytecollege.entity; import lombok.Data; @Data public class StudentInfo {     private int studentDetailId;     private int studentId;     private String mail;     private String telephone; } 新建cn.bytecollege.mapper接口,添加Mybatis映射器绑定的接口:package cn.bytecollege.mapper; import cn.bytecollege.entity.Student;  import java.util.List;  public interface StudentMapper {     List findAllStudent(); } package cn.bytecollege.mapper; import cn.bytecollege.entity.StudentInfo; import java.util.List; public interface StudentInfoMapper {     List findAllStudentDetail(); } 在resource目录下新建mapper路径,用于存放映射器文件。                  在resource目录下新建Mybatis配置文件:mybatis-config.xml<?xml version="1.0" encoding="UTF-8" ?>                                                           
  在Spring中整合Mybatis时,数据源和映射器位置可以在Spring配置文件中进行配置,因此在Mybatis配置文件中省略了数据源和映射器位置的配置。因此只配置了开启驼峰命名映射和生成实体类的别名。在resource目录下新建Spring配置文件:spring.xml<?xml version="1.0" encoding="UTF-8"?>                                                                                      				                                     				                                                                                                                                                                             	      
  在Spring配置文件中需要配置以下信息:配置扫描注解包配置加载数据连接信息文件配置数据源,因为使用了Druid连接池,所以此处配置了DruidDataSource配置事务管理器配置Mybatis中SqlsessionFactoryBean,在Spring容器启动时创建SqlsessionFactory,SqlSessionFactoryBean需要配置以下3个属性:dataSource:引用配置好的数据源configLocation:Mybatis全局配置文件mapperLocations:映射器所在位置配置扫描Mapper接口,MapperScannerConfigurer配置basePackage属性用于扫描同映射器绑定的接口,使用动态代理为其生成实现类代理
  至此,Spring中已经成功整合Mybatis,新建测试类并调用StudentMapper中查询方法,代码如下:package cn.bytecollege.test;  import cn.bytecollege.entity.Student; import cn.bytecollege.mapper.StudentMapper; import org.apache.log4j.Logger; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import java.util.List;  public class Test {     public static void main(String[] args) {         Logger log = Logger.getLogger(Test.class);         ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");         StudentMapper mapper = context.getBean(StudentMapper.class);         List list = mapper.findAllStudent();         list.forEach(e->log.info(e));     } }
  运行结果如下:
  5.2.2 Spring声明式事务
  从数据库的设计上可以看出student表和student_info表存在一对一的关系,也就是说在添加学生基本信息时,需要同时添加学生详细信息,或者在学生详细信息中先添加一条占位数据,先不使用事务并在代码中抛出异常:
  在接口中添加方法:package cn.bytecollege.mapper; import cn.bytecollege.entity.Student; import java.util.List;  public interface StudentMapper {     /**      * 查询所有学生      * @return      */     List findAllStudent();      /**      * 新增学生      * @param student      * @return      */     int addStudent (Student student); } package cn.bytecollege.mapper; import cn.bytecollege.entity.StudentInfo; import java.util.List; public interface StudentInfoMapper {     /**      * 查询所有学生信息      * @return      */     List findAllStudentDetail();      /**      * 新增学生信息      * @param studentInfo      * @return      */     int addStudentInfo(StudentInfo studentInfo); }
  在映射器中添加对应的SQL语句                    insert into student (student_name, student_age, student_gender)         values         (#{studentName},#{studentAge},#{studentGender});                          insert into student_info (STUDENT_ID, MAIL, TELEPHONE)         values         (#{studentId},#{mail},#{telephone})      
  新建测试类:package cn.bytecollege.test;  import cn.bytecollege.entity.Student; import cn.bytecollege.entity.StudentInfo; import cn.bytecollege.mapper.StudentInfoMapper; import cn.bytecollege.mapper.StudentMapper; import org.apache.log4j.Logger; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import java.util.List;  public class Test {     public static void main(String[] args) {         Logger log = Logger.getLogger(Test.class);         ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");          StudentMapper studentMapper = context.getBean(StudentMapper.class);         StudentInfoMapper studentInfoMapper = context.getBean(StudentInfoMapper.class);          Student student = new Student();         student.setStudentAge(18);         student.setStudentName("李雷");         student.setStudentGender("男");          StudentInfo studentInfo = new StudentInfo();         studentInfo.setMail("lilei@163.com");         studentInfo.setTelephone("17765213454");          studentMapper.addStudent(student);         //1.抛出异常         System.out.println(5/0);         studentInfo.setStudentId(student.getStudentId());         studentInfoMapper.addStudentInfo(studentInfo);     } }
  在测试类中注释1处人为抛出异常,运行测试类可以看出student表中添加了数据,但是student_info表中并没有添加数据,显然这违背了事务的原子性。运行结果如下图:
  为了方便使用Spring声明式事务,新建StudentService类,代码如下:package cn.bytecollege.service;  import cn.bytecollege.entity.Student; import cn.bytecollege.entity.StudentInfo; import cn.bytecollege.mapper.StudentInfoMapper; import cn.bytecollege.mapper.StudentMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @Service public class StudentService {     @Autowired     private StudentMapper studentMapper;     @Autowired     private StudentInfoMapper studentInfoMapper;     @Transactional     public void add(Student student,StudentInfo studentInfo){         studentMapper.addStudent(student);         //1.抛出异常         System.out.println(5/0);         studentInfo.setStudentId(student.getStudentId());         studentInfoMapper.addStudentInfo(studentInfo);     } }
  可以看出在add()中认为抛出了异常,并且在方法上添加了@Transactional注解,该注解将会在下一小节进行讲解。
  新建测试类,进行测试。package cn.bytecollege.test;  import cn.bytecollege.entity.Student; import cn.bytecollege.entity.StudentInfo; import cn.bytecollege.service.StudentService; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;  public class Test {     public static void main(String[] args) {         ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");          StudentService studentService = context.getBean(StudentService.class);          Student student = new Student();         student.setStudentName("李雷");         student.setStudentAge(18);         student.setStudentGender("男");          StudentInfo studentInfo = new StudentInfo();         studentInfo.setMail("lilei@163.com");         studentInfo.setTelephone("17765878821");          studentService.add(student,studentInfo);     } }
  运行测试类可以看出数据库中数据并没有添加,也就是说数据库事务回滚了,此时删除StudentService中注释1处的代码,再次运行可以看出数据成功插入。5.2.3 @Transactional注解
  基于@Transactional注解的拥有一组普适性很强的默认事务属性,往往可以直接使用这些默认的属性。事务传播行为 PROPAGATION REQUIRED。事务隔离级别 ISOLATION_DEFAULT。读写事务属性 读/写事务。超时时间 依赖于底层的事务系统的默认值。回滚设置 任何运行期异常引发回滚,任何检查型异常不会引发回滚。
  这些默认设置在大多数情况下都是适用的,所以一般不需要手工设置事务注解的属性。
  属性
  说明
  Propagation事务传播行为,通过以下枚举类提供合法值:org.springframework.transaction.annotation.
  Propagation。例如:@Transactional(propagation = Propagation.REQUIRES_NEW)
  isolation事务隔离级别,通过一下枚举类提供合法值:
  org.springframework.transaction.annotation.Isolation例如 @Transactional(isolation=Isolation.READ_COMMITTED)
  readOnly
  事务读写性,布尔型。例如 @Transactional(readOnly=true)
  timeout
  超时时间,int 型,以秒为单位。例如 @Transactional(timeout=10)
  rollbackFor
  一组异常类,遇到时进行回滚,类型为 Class<?extends Throwable>[],默认值为{}。例如 @Transactional(rollbackFor={SQLException.class})。多个异常之间可用逗号分隔.
  rollbackForClassName
  一组异常类名,遇到时进行回滚,类型为String[],默认值为{}。例如:@Transactional(rollbackForClassName={SQLException})
  noRollbackFor
  一组异常类,遇到时不回滚,类型为Class<? extends Throwable>[],默认值为{}
  noRollbackForClassName
  一组异常类名,遇到时不回滚,类型为String[],默认值为{}5.3 Spring事务隔离级别
  Spring对事务的支持提供了5种隔离级别,各种隔离级别的含义如表所示。
  5.4 Spring事务传播行为
  事务传播行为是用来描述由某一个事务传播行为修饰的方法被嵌套进另一个方法的时候,事务的传播特性。Spring中定义了7种事务传播行为,如表所示。

瓦妮莎现身全明星!为保罗颁奖,拥抱丈夫好兄弟,全场高呼科比北京时间2月21日,保罗因在推动女子篮球进步和宣传WNBA方面的贡献,获得首届科比与吉安娜倡导奖,在NBA全明星正赛期,科比的遗孀瓦妮莎惊喜现身,为保罗颁奖,值得一提的是,记者还捕纯电续航里程401km,搭配清新的外观,哪吒V值得购买吗纯电续航里程401km,搭配清新的外观,哪吒V值得购买吗现如今,汽车行业的竞争也很激烈,各大汽车品牌为了吸引消费者的注意,就在外观上大显身手,毕竟颜值是吸引人们眼球最直接的方式。还很多怪病都是痰湿引发的,此文把痰湿说得一清二楚由于人体脾的运化水湿功能下降,或水液在体内的循环排泄过程中遇到障碍,水液就不能正常滋润人体,反而会在体内形成异常的积聚,成为一种病理物质。这种异常积聚的水液,中医就将它称为痰饮。其CarolinaHerrera2022秋冬系列全新CarolinaHerrera2022秋冬系列,创意总监WesGordon从CarolinaHerrera的品牌基因中汲取自信坚强热血的女性魅力特质,与盛开的鸢尾花碰撞出时尚灵汉麻混凝土亮相北京冬奥的未来材料国家雪车雪橇中心俯瞰图广东建设报记者王芷芸在北京延庆狭长山坡上,国家雪车雪橇中心的赛道犹如一条盘旋舞动的巨龙,因此也被称为雪游龙。近日,来自世界各地的运动员在此进行着2022年北京王耀庆曾因一件事差点妻离子散,婚后养育两子,娶个媳妇旺三代王耀庆王耀庆,一个演不了穷人的男演员,在他的演绎生涯中大多饰演的都是霸道总裁或者是上层顶流。这让观众们也对王耀庆产生了固有印象,王耀庆为啥不演穷人呢?其实这还是跟他身上的气质有关,黄大宪直播回应争议对我的攻击越多,越证明我们国家强大2022北京冬奥会诞生了许多明星级运动员,谷爱凌武大靖羽生结弦等实力圈粉,爆红全网,俄罗斯三娃更是无数网友心目中的掌上明珠。有的运动员也红了,但红得不怎么光彩,比如韩国短道速滑选手盘点冬奥会赛场内外的催泪时刻冬奥会临近闭幕,2022北京冬奥会马上进入尾声。在这场世界盛宴中,发生了太多太多超治愈的场景。这一切深深地诠释了本届奥林匹克运动会更快更高更强更团结的口号。那么,我们来逐个列举一下央行新规,这钱我们到底该怎么存取伙伴们,大家好。随着这两年经济的发展,现在手里有余款的伙伴们估计也是越来越多了。然而正值新春佳节之际,一则重磅消息登上了热搜,央行发布了金融机构客户尽职调查和客户身份资料及交易记录二月下旬这四个板块或将迎来大幅上涨一东数西算板块。东数西算板块在这周横空出世,这个板块周五大涨9。33,爆发了涨停潮。东数西算板块之所以大涨,这源于国家发改委等部门联合印发文件,同意在京津冀长三角粤港澳大湾区成渝内下周重点关注这三大板块的爆发机会,东数西算有望迎来高爆发一东数西算工程全面启动所谓东数西算,通俗地讲,数据和算力,就是指把东部的数据流动到西部存储计算,如同南水北调西电东送。此概念经过周末利好消息刺激,持续发酵,下周有望迎来高爆发,其中
如果你不想分享,就不要炫耀1hr人永远都无法知道自己该要什么,因为人只能活一次,既不能拿它跟前世相比,也不能在来生加以修正。一切都是马上经历,仅此一次,不能准备,好像一个演员没有排练就上了舞台。如果生命的初2022年各大品牌口红广告语你喜欢哪一个纪梵希一生只做一件事,一生只爱一个人,别说时间不值得,你最值得我爱你,你随意迪奥(DIOR)我目光短浅,眼里只有你,我有两个心愿,你在身边,在你身边香奈儿(CHANEL威联通NAS入手安装以及入门实录,以TS416为例我在头条搞创作第二期大家好,我是聚灵阵主。随着个人拍摄的数据越来越多,我终于准备换一个专业NAS用来永久保存重要资料了,主要是使用威联通文件共享以及文件整理功能,同时还要感谢加勒比香港宣布入境免隔离,核酸取消!澳洲赴香港航班,搜索量瞬间暴涨前言香港最近放宽限制的速度,简直就像是坐上了火箭,前两天还在积极考虑07,昨天就正式宣布免隔离,好消息简直来得让人措不及防!01香港再放宽政策,入境直接免隔离随着全球新冠疫情逐渐放孩子的性教育,您重视了吗?现代人追求的是生活的质量,他们努力工作赚钱,可以买大房子买好车,给孩子报兴趣班,带孩子去旅游,物质生活是越来越好了。然而,许多家长在忙于工作之余,却忽视了一件关系到子女终身幸福的大微服务改造过程中那些必须重视的问题微服务近几年尤其火热,各大厂都在进行微服务化改造和微服务建设,想享受微服务化带来的好处以便对自己的系统进行改造。分布式实验室特约记者李鹏采访了广州轻阅科技系统架构师陈珙,就微服务与我国天文学家利用郭守敬望远镜发现一颗宁静态中子星新京报讯(记者张璐)记者从中国科学院国家天文台获悉,基于国家重大科技基础设施郭守敬望远镜(LAMOST)时域巡天数据,LAMOST黑洞猎手计划研究团队发现了一颗距离地球大约1037儿童便秘对孩子的七大危害,家长一定要重视,教你五招来改善我们常常听说谁家孩子有几天不大便了,又听说孩子小,不用管,大了就好了!事实真的如此吗?长期便秘有哪些危害?1影响孩子的食欲食物残渣存留在体内,胃肠蠕动减慢,宝宝觉得腹内胀气,这样一肖战七年红毯气场变化,如今的他乘风破浪步步生辉肖战挑战七年红毯气场变化2016年随组合亮相红毯,脸上青涩懵懂,此时的他还只是个小透明,2017年依旧和组合同框,不变的还是走在最后面,但脸上圆嘟嘟,笑起来很是可爱呆萌。2018的今年起,普通人做好资产贬值的准备?建议不要做4件事这一年,大多数人都能明显感受到生活成本的上涨,手里的钱能买的东西越来越少,手里的货币贬值越来越快。不仅如此,手中的资产也开始贬值。房地产是最明显的一点。全国平均房价从去年的1100这些明星款口红,你会pick哪一支?口红千千万,唯有新的最好看大家好,今天给大家推荐几支明星款口红,它们是时代的过客还是常青树?如果给你选,你会pick哪一支?其实还有很多其他的颜色,个人觉得这几支算是知名度比较高的