技术内幕

Mybatis3.3.x技术内幕(三):Mybatis事务管理(将颠覆你心中目前对事务的理解)

那年仲夏 提交于 2020-03-20 20:53:40
3 月,跳不动了?>>> 1.说到数据库事务,人们脑海里自然不自然的就会浮现出事务的四大特性、四大隔离级别、七大传播特性。四大还好说,问题是七大传播特性是哪儿来的?是Spring在当前线程内,处理多个数据库操作方法事务时所做的一种事务应用策略。事务本身并不存在什么传播特性,不要混淆事务本身和Spring的事务应用策略。(当然,找工作面试时,还是可以巧妙的描述传播特性的) 2.一说到事务,人们可能又会想起create、begin、commit、rollback、close、suspend。可实际上,只有commit、rollback是实际存在的,剩下的create、begin、close、suspend都是虚幻的,是业务层或数据库底层应用语意,而非JDBC事务的真实命令。 create(事务创建):不存在。 begin(事务开始):姑且认为存在于DB的命令行中,比如Mysql的start transaction命令,以及其他数据库中的begin transaction命令。JDBC中不存在。 close(事务关闭):不存在。应用程序接口中的close()方法,是为了把connection放回数据库连接池中,供下一次使用,与事务毫无关系。 suspend(事务挂起):不存在。Spring中事务挂起的含义是,需要新事务时,将现有的connection1保存起来(它还有尚未提交的事务)

Mybatis3.3.x技术内幕(十一):执行一个Sql命令的完整流程

混江龙づ霸主 提交于 2020-03-04 17:36:54
Mybatis中的Sql命令,在枚举类SqlCommandType中定义的。 public enum SqlCommandType { UNKNOWN, INSERT, UPDATE, DELETE, SELECT, FLUSH; } 下面,我们以Mapper接口中的一个方法作为例子,看看Sql命令的执行完整流程。 public interface StudentMapper { List<Student> findAllStudents(Map<String, Object> map, RowBounds rowBounds, ResultSetHandler rh); } 参数RowBounds和ResultSetHandler是可选参数,表示分页对象和自定义结果集处理器,一般不需要。 一个完整的Sql命令,其执行的完整流程图如下: (Made In Edrawmax) 对于上面的流程图,如果看过前面的博文的话,大部分对象我们都比较熟悉了。一个图,就完整展示了其执行流程。 MapperProxy的功能: 1. 因为Mapper接口不能直接实例化, MapperProxy的作用,就是使用JDK动态代理功能,间接实例化Mapper的proxy对象。可参看系列博文的第二篇。 2. 缓存 MapperMethod对象。 private final Map<Method,

Mybatis3.4.x技术内幕(二十一):参数设置、结果封装、级联查询、延迟加载原理分析

你离开我真会死。 提交于 2019-12-16 15:44:42
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> Mybatis在执行查询时,其参数设置、结果封装、级联查询、延迟加载,是最基本的功能和用法,我们有必要了解其工作原理,重点阐述级联查询和延迟加载。 1、MetaObject MetaObject用于反射创建对象、反射从对象中获取属性值、反射给对象设置属性值,参数设置和结果封装,用的都是这个MetaObject提供的功能。 public static MetaObject forObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory, ReflectorFactory reflectorFactory) { if (object == null) { return SystemMetaObject.NULL_META_OBJECT; } else { return new MetaObject(object, objectFactory, objectWrapperFactory, reflectorFactory); } } public Object getValue(String name) { //... } public void setValue(String name,

Mybatis3.4.x技术内幕(二十二):Mybatis一级、二级缓存原理分析

↘锁芯ラ 提交于 2019-11-29 11:18:48
Mybatis的一级缓存,指的是SqlSession级别的缓存,默认开启;Mybatis的二级缓存,指的是SqlSessionFactory级别的缓存,需要配置。缓存是针对select来说的。 1、一级缓存 <configuration> <settings> <setting name="localCacheScope" value="SESSION|STATEMENT" /> </settings> </configuration> localCacheScope用于配置一级缓存的范围,默认值是SESSION,表示SqlSession范围; 如果配置为STATEMENT,则表示SqlSession范围内的一个查询范围,但它并不是一个Statement实例范围。 STATEMENT举例:查询Student对象发送一次sql查询,紧接着再发一次sql查询关联的Teacher对象,这个完整过程称之为一个查询。 一级缓存默认开启,且没有全局关闭的配置开关。 <select ... flushCache="false" useCache="true|false"/> flushCache:同时影响了一级、二级缓存,flushCache=true,会导致清空本条sql(当前MappedStatement)的一级、二级缓存,注意是当前的,不影响其他的MappedStatement。

Mybatis3.3.x技术内幕(九):Mybatis初始化流程(中)

ぐ巨炮叔叔 提交于 2019-11-28 12:56:14
Mybatis初始化流程,其实就是组装重量级All-In-One对象Configuration的过程,主要分为系统环境参数初始化和Mapper映射初始化。 上一节中,粗略讲述了 Mybatis初始化的基本步骤,本节,将详细分析具体的初始化过程中的细节问题,细节决定成败。 1. Properties variables的作用 通常,我们会单独配置jdbc.properties文件,保存于 variables变量中, 而Xml文件内可以使用${driver}占位符,读取时可动态替换占位符的值。 String value = PropertyParser.parse(attribute.getNodeValue(), variables); Mybatis中的PropertyParser类,就是用来动态替换占位符参数的。 2. 扫描package <typeAliases> <typeAlias alias="Student" type="com.mybatis3.domain.Student" /> <typeAlias alias="Teacher" type="com.mybatis3.domain.Teacher" /> <package name="com.mybatis3.domain" /> </typeAliases> 前两个typeAlias,很容易理解,那么

Mybatis3.3.x技术内幕(七):Mybatis初始化之六个工具

喜夏-厌秋 提交于 2019-11-28 12:56:01
全民欢庆的五一劳动节,可谓是赏花赏月赏秋香的好季节,炎炎夏日,柳絮飞扬,短裙飞舞,低胸抢镜,是旅游撩妹裸奔等精彩活动的不二选择,不过,这显然与我无关。 终于要开启Mybatis的初始化过程分析了,是不是等的花儿都要开放了呢? 一般的框架分析思路都是从启动、初始化说起,然而,由于没有心理准备,初始化过程中会瞬间涌入大量的概念、类等等,类之间又存在爆炸性延伸,反而吓退了读者,有种吃不下这块肥肉的感觉。所以,我选择优先介绍一些易于理解的框架概念,然后再阅读和分析框架的启动和初始化流程,有了事先的精心准备,肥肉也就不再肥了。 我一直在反思,我的博文是否写的过长了,读者是否读的很累,是否没有描述清楚内容,是否没有抓住重点。因此,我大胆创新了博文的写作模式,叫 精炼博文 。 Mybatis的初始化过程,就是组装Configuration的过程,在这个过程中,用到了一些工具,我列举了六个基本工具,如图所示。 (Made In Edrawmax) 图中展示了XMLConfigBuilder为了组装出Configuration对象所作出的努力,配备了至少六个基本工具。本文的重点,就是分析这六个工具的作用。 好怕怕啊,一下子分析六个那么多。别怕,每个工具不超过三行代码,你就会彻底明白(相信你自己)。 1. ObjectFactory ObjectFactory objectFactory = new

Mybatis3.4.x技术内幕(十八):Mybatis之动态Sql设计原本(下)

无人久伴 提交于 2019-11-28 12:55:49
上一篇博文中,简要介绍了Mybatis动态sql的基本用法和基本设计结构,本篇博文重点阐述一些动态sql的技术细节, #{name}和${name}的区别 ,将在本篇博文中揭晓。也许读者早已了解它们之间的区别,但是,作为技术内幕,我们不仅要了解它们的区别,还要介绍它们的工作原理,是不是很开森呢? 1. #{name}和${name}的区别。 #{name}:表示这是一个参数(ParameterMapping)占位符,值来自于运行时传递给sql的参数,也就是XXXMapper.xml里的parameterType。其值通过PreparedStatement的setObject()等方法赋值。 动态sql中的<bind>标签绑定的值,也是使用#{name}来使用的。 #{name}用在sql文本中。 ${name}:表示这是一个属性配置占位符,值来自于属性配置文件,比如jdbc.properties,其值通过类似replace方法进行静态替换。比如${driver},将被静态替换为com.mysql.jdbc.Driver。 ${name}则可以用在xml的Attribute属性,还可以用在sql文本当中。 <select id="countAll" resultType="${driver}"> select count(1) from ( select stud_id as

Mybatis3.4.x技术内幕(十七):Mybatis之动态Sql设计原本(上)

匆匆过客 提交于 2019-11-28 12:55:32
上一篇博文中,介绍了可复用的sql片段,通过<include>标签进行引入,而<include>标签内一般存放的是静态sql,其实,sql片段也是可以放置动态sql标签内容。 1. Mybatis支持的动态sql及基本用法 org.apache.ibatis.scripting.xmltags.XMLScriptBuilder.nodeHandlers(String)部分源码。 NodeHandler nodeHandlers(String nodeName) { Map<String, NodeHandler> map = new HashMap<String, NodeHandler>(); map.put("trim", new TrimHandler()); map.put("where", new WhereHandler()); map.put("set", new SetHandler()); map.put("foreach", new ForEachHandler()); map.put("if", new IfHandler()); map.put("choose", new ChooseHandler()); map.put("when", new IfHandler()); map.put("otherwise", new OtherwiseHandler(

Mybatis3.4.x技术内幕(二十三):Mybatis面试问题集锦(大结局)

生来就可爱ヽ(ⅴ<●) 提交于 2019-11-28 12:54:04
Mybatis技术内幕系列博客,从原理和源码角度,介绍了其内部实现细节,无论是写的好与不好,我确实是用心写了,由于并不是介绍如何使用Mybatis的文章,所以,一些参数使用细节略掉了,我们的目标是介绍Mybatis的技术架构和重要组成部分,以及基本运行原理。 博客写的很辛苦,但是写出来却不一定好看,所谓开始很兴奋,过程很痛苦,结束很遗憾。要求不高,只要读者能从系列博客中,学习到一点其他博客所没有的技术点,作为作者,我就很欣慰了,我也读别人写的博客,通常对自己当前研究的技术,是很有帮助的。 尽管还有很多可写的内容,但是,我认为再写下去已经没有意义,任何其他小的功能点,都是在已经介绍的基本框架和基本原理下运行的,只有结束,才能有新的开始。写博客也积攒了一些经验,源码多了感觉就是复制黏贴,源码少了又觉得是空谈原理,将来再写博客,我希望是“ 精炼博文 ”,好读好懂美观读起来又不累,希望自己能再写一部开源分布式框架原理系列博客。 有胆就来,我出几道Mybatis面试题,看你能回答上来几道(都是我出的,可不是网上找的)。 1、#{}和${}的区别是什么? 注:这道题是面试官面试我同事的。 答: ${} 是Properties文件中的变量占位符,它可以用于标签属性值和sql内部,属于静态文本替换,比如 ${driver} 会被静态替换为com.mysql.jdbc.Driver。 #{}

Mybatis3.4.x技术内幕(十六):Mybatis之sqlFragment(可复用的sql片段)

冷暖自知 提交于 2019-11-28 12:53:49
Mybatis目前最新版本为3.4.0,因此,我也将我的项目由3.3.1替换为3.4.0。在上一篇博文中,详细分析了Mybatis在使用foreach循环进行批量insert,返回主键id列表时,如果使用BatchExecutor,那么由于Mybatis存在bug,返回的id列表将是null值。很遗憾的告诉大家,Mybatis3.4.0依然是没有修复该bug的,该bug依然存在。 今天,我们将分析Mybatis之sqlFragment,可以翻译为sql片段,它的存在价值在于可复用sql片段,避免到处重复编写。 在工作中,往往有这样的需求,对于同一个sql条件查询,首先需要统计记录条数,用以计算pageCount,然后再对结果进行分页查询显示,看下面一个例子。 <sql id="studentProperties"><!--sql片段--> select stud_id as studId , name, email , dob , phone from students </sql> <select id="countAll" resultType="int"> select count(1) from ( <include refid="studentProperties"></include><!--复用--> ) tmp </select> <select id=