Java开发面试问题,Java中高级核心知识全面解析(10)
}
## 2. Spring 事务管理接口介绍
Spring 框架中,事务管理相关最重要的 3 个接口如下:- `PlatformTransactionManager` : (平台)事务管理器,Spring 事务策略的核心。- `TransactionDefinition` : 事务定义信息(事务隔离级别、传播行为、超时、只读、回滚规则)。- `TransactionStatus` : 事务运行状态。我们可以把 `PlatformTransactionManager` 接口可以被看作是事务上层的管理者,而 `TransactionDefinition 和 TransactionStatus` 这两个接口可以看作是事物的描述。`PlatformTransactionManager` 会根据 `TransactionDefinition` 的定义比如事务超时时间、隔离界别、传播行为等来进行事务管理 ,而 `TransactionStatus` 接口则提供了一些方法来获取事务相应的状态比如是否新事务、是否可以回滚等等。
### 1)PlatformTransactionManager:事务管理接口
**Spring 并不直接管理事务,而是提供了多种事务管理器** 。Spring 事务管理器的接口是:`PlatformTransactionManager` 。通过这个接口,Spring 为各个平台如 JDBC( `DataSourceTransactionManager` )、Hibernate( `HibernateTransactionManager` )、JPA( `JpaTransactionManager `)等都提供了对应的事务管理器,但是具体的实现就是各个平台自己的事情了。`PlatformTransactionManager` **接口的具体实现如下:**
![](https://upload-images.jianshu.io/upload_images/25222111-7f456d31d5a95825?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
`PlatformTransactionManager` 接口中定义了三个方法:
```java
package org.springframework.transaction; import org.springframework.lang.Nullable; public interface PlatformTransactionManager { //获得事务 TransactionStatus getTransaction(@Nullable TransactionDefinition var1) throws TransactionException; //提交事务 void commit(TransactionStatus var1) throws TransactionException; //回滚事务 void rollback(TransactionStatus var1) throws TransactionException;
}
这里多插一嘴。为什么要定义或者说抽象出来 PlatformTransactionManager
这个接口呢?
主要是因为要将事务管理行为抽象出来,然后不同的平台去实现它,这样我们可以保证提供给外部的行为不变,方便我们扩展。我前段时间分享过:“为什么我们要用接口?”
2)TransactionDefinition:事务属性
事务管理器接口 PlatformTransactionManager
通过 getTransaction(TransactionDefinition definition)
方法来得到一个事务,这个方法里面的参数是 TransactionDefinition
类 ,这个类就定义了一些基本的事务属性。
那么什么是 事务属性 呢?
事务属性可以理解成事务的一些基本配置,描述了事务策略如何应用到方法上。
事务属性包含了 5 个方面:
TransactionDefinition
接口中定义了 5 个方法以及一些表示事务属性的常量比如隔离级别、传播行为等等。
package org.springframework.transaction; import org.springframework.lang.Nullable; 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; // 返回事务的传播行为,默认值为 REQUIRED。 int getPropagationBehavior(); //返回事务的隔离级别,默认值是 DEFAULT int getIsolationLevel(); // 返回事务的超时时间,默认值为-1。如果超过该时间限制但事务还没有完成,则自动回滚事务。 int getTimeout(); // 返回是否为只读事务,默认值为 false boolean isReadOnly(); @Nullable String getName();
}
3)TransactionStatus:事务状态
TransactionStatus
接口用来记录事务的状态 该接口定义了一组方法,用来获取或判断事务的相应状态信息。
PlatformTransactionManager.getTransaction(…)
方法返回一个TransactionStatus
对象。
TransactionStatus 接口接口内容如下:
public interface TransactionStatus{ boolean isNewTransaction(); // 是否是新的事物 boolean hasSavepoint(); // 是否有恢复点 void setRollbackOnly(); // 设置为只回滚 boolean isRollbackOnly(); // 是否为只回滚 boolean isCompleted; // 是否已完成
}
3.事务属性详解
实际业务开发中,大家一般都是使用 @Transactional
注解来开启事务,很多人并不清楚这个参数里 面的参数是什么意思,有什么用。为了更好的在项目中使用事务管理,强烈推荐好好阅读一下下面的内容。
1)事务传播行为
事务传播行为是为了解决业务层方法之间互相调用的事务问题。
当事务方法被另一个事务方法调用时,必须指定事务应该如何传播。例如:方法可能继续在现有事务中运行,也可能开启一个新事务,并在自己的事务中运行。
举个例子!
我们在 A 类的 aMethod()
方法中调用了 B 类的 bMethod()
方法。这个时候就涉及到业务层方法之间互相调用的事务问题。如果我们的 bMethod()
如果发生异常需要回滚,如何配置事务传播行为才能让aMethod()
也跟着回滚呢?这个时候就需要事务传播行为的知识了,如果`你不知道的话一定要好好看一下。
Class A { @Transactional(propagation=propagation.xxx) public void aMethod { //do something B b = new B(); b.bMethod(); }
}Class B { @Transactional(propagation=propagation.xxx) public void bMethod { //do something }
}
在 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; ......
}
不过如此,为了方便使用,Spring会相应地定义了一个枚举类:Propagation
package org.springframework.transaction.annotation; import org.springframework.transaction.TransactionDefinition; public enum Propagation { REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED), SUPPORTS(TransactionDefinition.PROPAGATION_SUPPORTS), MANDATORY(TransactionDefinition.PROPAGATION_MANDATORY),REQUIRES_NEW(TransactionDefinition.PROPAGATION_REQUIRES_NEW), NOT_SUPPORTED(TransactionDefinition.PROPAGATION_NOT_SUPPORTED), NEVER(TransactionDefinition.PROPAGATION_NEVER), NESTED(TransactionDefinition.PROPAGATION_NESTED); private final int value; Propagation(int value) { this.value = value; }public int value() { return this.value; }
}
正确的事务传播行为可能的值如下 :
1_ TransactionDefinition.PROPAGATION_REQUIRED
使用的最多的一个事务传播行为,我们平时经常使用的 @Transactional
注解默认使用就是这个事务传播行为。如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。也就是说:
- 如果外部方法没有开启事务的话,
Propagation.REQUIRED
修饰的内部方法会新开启自己的事务,且开启的事务相互独立,互不干扰。 - 如果外部方法开启事务并且被
Propagation.REQUIRED
的话,所有Propagation.REQUIRED
修饰的内部方法和外部方法均属于同一事务 ,只要一个方法回滚,整个事务均回滚。
举个例子:如果我们上面的 aMethod()
和 bMethod()
使用的都是 PROPAGATION_REQUIRED
传播行为的话,两者使用的就是同一个事务,只要其中一个方法回滚,整个事务均回滚。
Class A { @Transactional(propagation=propagation.PROPAGATION_REQUIRED) public void aMethod { //do something B b = new B(); b.bMethod(); }
}Class B { @Transactional(propagation=propagation.PROPAGATION_REQUIRED) public void bMethod { //do something }
}
2_TransactionDefinition.PROPAGATION_REQUIRES_NEW
创建一个新的事务,如果当前存在事务,则把当前事务挂起。也就是说不管外部方法是否开启事务,Propagation.REQUIRES_NEW
修饰的内部方法会新开启自己的事务,且开启的事务相互独立,互不干扰。
举个例子:如果我们上面的 bMethod()
使用 PROPAGATION_REQUIRES_NEW
事务传播行为修饰,aMethod
还是用 PROPAGATION_REQUIRED
修饰的话。如果 aMethod()
发生异常回滚, bMethod()
不会跟着回滚,因为 bMethod()
开启了独立的事务。但是,如果 bMethod()
抛出了未被捕获的异常并且这个异常满足事务回滚规则的话, aMethod()
同样也会回滚,因为这个异常被 aMethod()
的事务管理机制检测到了。
Class A { @Transactional(propagation=propagation.PROPAGATION_REQUIRED) public void aMethod { //do something B b = new B(); b.bMethod(); }
}Class B { @Transactional(propagation=propagation.REQUIRES_NEW) public void bMethod { //do something }
}
3_TransactionDefinition.PROPAGATION_NESTED
:
如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于 TransactionDefinition.PROPAGATION_REQUIRED
。也就是说:
- 在外部方法未开启事务的情况下
Propagation.NESTED
和Propagation.REQUIRED
作用相同,修饰的内部方法都会新开启自己的事务,且开启的事务相互独立,互不干扰。 - 如果外部方法开启事务的话,
Propagation.NESTED
修饰的内部方法属于外部事务的子事务,外部主事务回滚的话,子事务也会回滚,而内部子事务可以单独回滚而不影响外部主事务和其他子事务。
这里还是简单举个例子:
如果 aMethod()
回滚的话, bMethod()
和 bMethod2()
都要回滚,而 bMethod()
回滚的话,并不会造成 aMethod()
和 bMethod()
回滚。
Class A { @Transactional(propagation=propagation.PROPAGATION_REQUIRED) public void aMethod { //do something B b = new B(); b.bMethod(); b.bMethod2(); }
}Class B { @Transactional(propagation=propagation.PROPAGATION_NESTED) public void bMethod { //do something }@Transactional(propagation=propagation.PROPAGATION_NESTED) public void bMethod2 { //do something }
}
4_ TransactionDefinition.PROPAGATION_MANDATORY
如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。(mandatory:强制性)
这个使用的很少,就不举例子来说了。
若是错误的配置以下 3 种事务传播行为,事务将不会发生回滚,这里不对照案例讲解了,使用的很少。
TransactionDefinition.PROPAGATION_SUPPORTS
: 如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。TransactionDefinition.PROPAGATION_NOT_SUPPORTED
: 以非事务方式运行,如果当前存在事务,则把当前事务挂起。TransactionDefinition.PROPAGATION_NEVER
: 以非事务方式运行,如果当前存在事务,则抛出异常。
2)事务隔离级别
TransactionDefinition
接口中定义了五个表示隔离级别的常量:
public interface TransactionDefinition { ...... int ISOLATION_DEFAULT = -1; int ISOLATION_READ_UNCOMMITTED = 1; int ISOLATION_READ_COMMITTED = 2; int ISOLATION_REPEATABLE_READ = 4; int ISOLATION_SERIALIZABLE = 8; ......
}
和事务传播行为这块一样,为了方便使用,Spring 也相应地定义了一个枚举类: Isolation
public enum Isolation { DEFAULT(TransactionDefinition.ISOLATION_DEFAULT), READ_UNCOMMITTED(TransactionDefinition.ISOLATION_READ_UNCOMMITTED), READ_COMMITTED(TransactionDefinition.ISOLATION_READ_COMMITTED), REPEATABLE_READ(TransactionDefinition.ISOLATION_REPEATABLE_READ), SERIALIZABLE(TransactionDefinition.ISOLATION_SERIALIZABLE); private final int value; Isolation(int value) { this.value = value; }public int value() { return this.value; }
}
下面我依次对每一种事务隔离级别进行介绍:
TransactionDefinition.ISOLATION_DEFAULT
:使用后端数据库默认的隔离级别,MySQL 默认采用的REPEATABLE_READ
隔离级别 Oracle 默认采用的READ_COMMITTED
隔离级别.TransactionDefinition.ISOLATION_READ_UNCOMMITTED
:最低的隔离级别,使用这个隔离级别很少,因为它允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读TransactionDefinition.ISOLATION_READ_COMMITTED
: 允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生TransactionDefinition.ISOLATION_REPEATABLE_READ
: 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。TransactionDefinition.ISOLATION_SERIALIZABLE
: 最高的隔离级别,完全服从 ACID 的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。
因为平时使用 MySQL 数据库比较多,这里再多提一嘴!
MySQL InnoDB 存储引擎的默认支持的隔离级别是 REPEATABLE-READ
(可重读)。我们可以通过SELECT @@tx_isolation;
命令来查看,如下:
这里需要注意的是:与 SQL 标准不同的地方在于 InnoDB 存储引擎在 REPEATABLE-READ
(可重读)事务隔离级别下使用的是 Next-Key Lock 锁算法,因此可以避免幻读的产生,这与其他数据库系统(如
SQL Server)是不同的。所以说 InnoDB 存储引擎的默认支持的隔离级别是 REPEATABLE-READ
(可重读) 已经可以完全保证事务的隔离性要求,即达到了 SQL 标准的 SERIALIZABLE
(可串行化) 隔离级别。
因为隔离级别越低,事务请求的锁越少,所以大部分数据库系统的隔离级别都是 READ-COMMITTED
(读取提交内容) :,但是你要知道的是 InnoDB 存储引擎默认使用 REPEATABLE-READ
(可重读) 并不会什么任何性能上的损失。
3)事务超时属性
所谓事务超时,就是指一个事务所允许执行的最长时间,如果超过该时间限制但事务还没有完成,则自动回滚事务。在 TransactionDefinition
中以 int 的值来表示超时时间,其单位是秒,默认值为-1。
4)事务只读属性
package org.springframework.transaction; import org.springframework.lang.Nullable; public interface TransactionDefinition { ...... // 返回是否为只读事务,默认值为 false boolean isReadOnly();
}
对于只有读取数据查询的事务,可以指定事务类型为 readonly,即只读事务。只读事务不涉及数据的修改,数据库会提供一些优化手段,适合用在有多条数据库查询操作的方法中。
很多人就会疑问了,为什么我一个数据查询操作还要启用事务支持呢?
MySQL 默认对每一个新建立的连接都启用了 autocommit 模式。在该模式下,每一个发送到MySQL 服务器的 sql 语句都会在一个单独的事务中进行处理,执行结束后会自动提交事务,并开启一个新的事务。
但是,如果你给方法加上了 Transactional
注解的话,这个方法执行的所有 sql 会被放在一个事务中。如果声明了只读事务的话,数据库就会去优化它的执行,并不会带来其他的什么收益。
最后
无论是哪家公司,都很重视基础,大厂更加重视技术的深度和广度,面试是一个双向选择的过程,不要抱着畏惧的心态去面试,不利于自己的发挥。同时看中的应该不止薪资,还要看你是不是真的喜欢这家公司,是不是能真的得到锻炼。
针对以上面试技术点,我在这里也做一些资料分享,希望能更好的帮助到大家。
戳这里免费领取以下资料
来其他的什么收益。
最后
无论是哪家公司,都很重视基础,大厂更加重视技术的深度和广度,面试是一个双向选择的过程,不要抱着畏惧的心态去面试,不利于自己的发挥。同时看中的应该不止薪资,还要看你是不是真的喜欢这家公司,是不是能真的得到锻炼。
针对以上面试技术点,我在这里也做一些资料分享,希望能更好的帮助到大家。
戳这里免费领取以下资料
[外链图片转存中…(img-Gaikvv7g-1628071671869)]
[外链图片转存中…(img-x5bS7854-1628071671871)]
[外链图片转存中…(img-fmvbxI1J-1628071671872)]
Java开发面试问题,Java中高级核心知识全面解析(10)相关推荐
- java file取不到linux文件_Java中高级核心知识全面解析——Linux基本命令(切换、增删改查、压缩文件、权限命令)...
一.目录切换命令 cd usr: 切换到该目录下usr目录 cd ..(或cd../): 切换到上一层目录 cd /: 切换到系统根目录 cd ~: 切换到用户主目录 cd -: 切换到上一个操作所在 ...
- Java中高级核心知识全面解析——常用框架(SpringMVC-工作原理详解)
一.先来看一下什么是 MVC 模式 MVC 是一种设计模式. MVC 的原理图如下: 二.SpringMVC 简单介绍 SpringMVC 框架是以请求为驱动,围绕 Servlet 设计,将请求发给控 ...
- java 数学公式解析框架有哪些_java程序员该如何进阶?这份java中高级核心知识全面解析请收好...
<Java中高级核心知识全面解析>是整理收录GitHub50K+Star以上的高质量学习文档,前前后后花了近半个月的时间,终于整理而成.包含了Java基础.网络.Linux.数据结构与算法 ...
- Java中高级核心知识全面解析
前言 今天给大家推荐一本PDF文档<Java中高级核心知识全面解析>这份文档总页数:524页.分为八个部分每个部分详细地讲解了核心知识点. 第一部分 扎实的Java基础 ( Java基础+ ...
- 呵呵,阿里高工熬夜手写“Java中高级核心知识全面解析”就这?也就让我五体投地的水平!
前言 先说一下自己的个人情况,大专生,18年通过校招进入湖南金蝶软件公司,干了接近3年的CRUD,今年年初,感觉自己不能够在这样下去了,长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了三 ...
- Java中高级核心知识全面解析——什么是Spring Cloud、需要掌握哪些知识点?(下)
目录 一.必不可少的 Hystrix 1.什么是 Hystrix之熔断和降级 2.什么是Hystrix之其他 二.微服务网关--Zuul 1.Zuul 的路由功能 1)简单配置 2)统一前缀 3)路由 ...
- Java程序员必经的实践之路:Java中高级核心知识全面解析(11)
ThreadPoolTaskExecutor定义一些策略: ThreadPoolExecutor.AbortPolicy:抛出RejectedExecutionException来拒绝新任务的处理. ...
- 从CRUD到自身架构师的蜕变之路?全靠这份:Java中高级核心知识全面解析
Java 入门(基础概念与常识) Java 语法 基本数据类型 方法(函数) 2. Java 面向对象 ============= 类和对象 面向对象三大特征 修饰符 接口和抽象类 其它重要知识点 3 ...
- Java中高级核心知识全面解析(3),美团Java面试算法题
主服务器 需要将自己生成的 RDB 文件 发送给从服务器,这个发送操作会 消耗 主服务器 大量的网络资源 (带宽和流量),并对主服务器响应命令请求的时间产生影响: 接收到 RDB 文件的 从服务器 需 ...
最新文章
- Mysql学习之order by的工作原理
- 【错误记录】编译 ijkplayer 报错 (fatal error: ijksoundtouch/ijksoundtouch_wrap.h: No such file or directory )
- 有趣的MS Live Labs
- CountDownLatch应用及原理
- input date保存值_涛哥文集(36):R keras保存和还原模型
- 吴恩达老师深度学习,结课了
- Selenium UI自动化测试(一)环境配置
- Anchor 对象学习
- 阿里架构师:​程序员必须掌握的几项核心能力
- sqlite简单笔记
- 解码H264文件的一些基础知识
- 【IDEA类注释模板和方法注释模板】
- k2p刷机丢失eeprom_刷机经验分享,K2P无线路由器救砖必备,无线和MAC恢复窍门
- 闪迪u盘量产工具万能版_加密保护,更高性能!闪迪酷奂CZ74 U盘新品果然够惊艳...
- 人脸识别闸机系统解决方案
- 使用Struts标签的基本配置
- linux应用层读写event,Linux应用层获取鼠标坐标
- 46道史上最全Redis面试题
- 国家基金申请书撰写的共性问题(转)
- SQL Server 2005 Integration Services (SSIS) (3)–Business Intelligence Development Studio (BIDS)
热门文章
- opencv jni Android 实例笔记
- HRFormer,内存和参数降低40%
- TensorBoard logging requires TensorBoard version 1.15 or above
- 图像分类、目标检测、语义分割、实例分割和全景分割的区别
- dlib win32
- PriorBox 改进
- Python3 websocket server与client
- Opencv 去高光或镜面反射(illuminationChange)
- pytorch可视化 resnet50特征图
- win10 远程登录-出现身份验证错误[可能是由于CredSSP加密Oracle修正]