Mybatis---总结

MyBatis是什么

Mybatis首先是持久层框架,可以通过简单的xml和注解进行配置,将接口和java对象映射成数据库中的记录。

可以避免jdbc代码和手动设置参数和获取结果集的繁琐过程。因为使用jdbc去做数据库持久化的步骤很繁琐:

1. 连接数据库,设置驱动和数据库信息。

2. 创建连接connection

3. 创建statement然后执行sql,返回resultset

4. 手动处理resultset映射到java对象。

而只要通过简单的配置就能够使用mybatis帮你处理了。

 

Mybatis的组成

Mybatis主要有四个部分组成:

SqlSessionFactoryBuilder 工厂构造器

SqlSessionFactory 工厂类

SqlSession 会话。能够调用映射器,发送sql语句去执行并且返回结果,能够控制事务的提交和回滚。

映射器。能够将java接口和xml配置文件映射成SQL用来执行,也能够将执行结果映射成java对象。

 

Mybatis原理---反射

资料

http://www.iteye.com/topic/1123081

 


 

===概念

java反射机制是说在程序的运行过程中,对于任意一个类或者对象,都能够知道它的所有属性和方法和构造方法,能够创建新的对象;这种动态获取属性或者调用方法的功能叫做java反射机制。

 

对于反射来说,最重要的就是Class类,这是一种用来描述类的类。java中的每一个类都会有一个Class实例对象,用来封装这个类的信息,包括属性,接口,方法,构造函数等等。要使用反射的话都要先获取这个Class对象。

 

===Class对象什么时候创建的呢?被保存在虚拟机什么位置呢?

在类加载器加载的时候创建Class对象,保存在虚拟机的方法区中。

 

===创建Class类实例对象的方法有三种

1.通过类获取;Person.class

2.通过类的全限定名创建 Class.forName(com.java.Person);类加载器会做加载

3.通过对象获取,getClass()来创建。

4.获取当前线程的classloader来加载。

 

 

===使用Class.forName和直接通过类名获取Class对象引用有什么区别呢?

首先他们都会获取到Class对象引用,但是使用.class不会做初始化,使用Class.forName会做初始化。

类加载三个步骤:加载连接初始化。

实际上进行了三步操作:

1.虚拟机的类加载器加载了.class文件,首先查找并且导入Class对象

2.验证类中的字节码,为静态变量分配了内存空间,创建了对其他类的所有引用

3.进行初始化,进行静态初始化和静态初始化块。

 

 

===获取到Class类实例对象之后就能够调用他的一些方法,比如说最常见的就是newInstance()方法来创建一个对象,或者通过getMethod方法获取方法类对象,再调用invoke来执行方法。

Class cla = Person.class;

Object xiaoming = cla.newInstance();

 

===框架中如何使用反射呢?

框架中大量使用到反射机制,能够使得程序更加灵活。

举一个例子,比如说创建一个类Person,如果没有反射,那么你必须new 一个Person对象。这个时候如果person类需要修改,那么就要停下整个应用进行修改编译再运行。但是使用反射就不需要了,你只要修改配置文件就行,通过配置文件获取到对象的Class对象,然后通过Class对象的newInstance()方法来创建实例。    

 

Mybatis原理---jdk动态代理

===使用jdk动态代理的流程

1.创建接口

 

 

2.创建委托类实现接口

 

 

3.创建代理类实现invocationHandler接口,绑定委托类,实现invoke方法。

绑定委托类:使用Proxy.newProxyInstance方法来绑定委托类返回一个代理对象,传入三个参数:委托类的类加载器,委托类接口,代理类。

 

 

实现invoke代理方法

Object invoke(Object proxy, Method method, Object[] args) throws Throwable

proxy:  指代我们所代理的那个真实对象

method:  指代的是我们所要调用真实对象的某个方法的Method对象

args:  指代的是调用真实对象某个方法时接受的参数

 

 

 

 

最后就是创建代理类,绑定后直接调用代理类的方法就可以了。

 

 

 

 

Mybatis原理---Cglib动态代理

产生一个子类 通过方法拦截技术拦截所有父类方法的调用。 

 

 

核心---映射器MapperStatement

映射器mapper是接口和xml或者注解的组合。通过动态代理来真正的实现sql语句的查询和返回结果。因为xml配置文件中配置了接口的全路径,根据全路径和方法名就能够通过动态代理去做绑定代理类MapperProxy。执行代理类的invoke方法来做执行。

MapperProxy代理类---invoke方法---MapperMethod----execute---根据增删改查做相应的处理

映射器的结构

映射器包括三个核心:

MappedStatement对象,它保存了一个节点,对应xml配置中的一个(select/insert/delete/update)增删改查的操作节点。保存了sql,缓存信息,结果集,入参类型,返参类型等等信息。

SqlSource,是一个接口,提供boundSql对象的获取,boundsql对象用来组装sql语句。

BoundSql 建立sql和参数的地方。包含sql语句,parameterObject和parameterMappings三个部分其中

Parameter表示入参本身如果我们传入多个参数的时候,就会转化成一个map,

parameterMappings用来描述参数,描述参数的属性名称,类型,javaType,jdbcType等等重要信息。通过它可以实现参数和sql的结合。

以上就是重要的三个重要部分。

 

 

 

 

 

映射器的动态代理

执行的流程总结如下:

1. 首先会调用代理类mapperMethod的execute方法,传入sqlsession和入参。

2. 随后在execute方法中会判断所执行的方法是增删改查的哪个,调用相对应的sqlsession的方法去执行。

首先动态代理会去执行invoke方法

根据xml配置文件的接口全限定名和相应的方法能够生成动态代理类。调用动态代理类的invoke方法,在invoke方法中会判断是否是一个类,如果不是就是接口。因为是接口,那么就生成MapperMethod对象,然后执行execute方法,将sqlSession和运行的参数传递进去。

 

 

因为最后会执行execute方法,这个方法传入sqlSession和参数。

 

 

 

 

 

执行MapperMethod的execute方法

根据入参去执行相应的execute方法,会区分你是想做增删改查的哪个操作。

 

 

根据上下文条件会跳转到相应的方法去执行。最后通过sqlSession的方法去执行。

 

 

 

 

 

核心---SqlSession的四大对象

映射器最后调用SqlSession的方法来执行数据库操作的,具体的执行时通过一系列的Handler来执行。四个核心为:

 

 

 

 

Executor执行器的类型

 

 

 

执行器有三种类型,根据用户的配置文件中的设置进行创建。

创建之后,通过插件设置一层层的动态代理对象。

和插件之间的关联

 

 

Executor的invoke方法执行

 

 

如何调用三个handler?

1. 使用StatementHandler做预编译。

2. 使用ParameterHandler设置参数完成预编译。

3. 执行查询后使用ResultSetHandler去包裹查询的结果。

StatementHandler

数据库会话器,根据使用的Executor会生成相应的StatementHandler,使用适配器的模式,通过switch…case判断executor来生成对应的handler。然后通过插件做代理对象的封装。

 

 

创建了StatementHandler后如何执行查询呢?

 

 

 

ParameterHandler设置参数

从参数对象parameterObject中取参数,然后通过typeHandler去进行参数处理后进行设置。然后执行sql语句。

ResultSetHandler结果处理器

对查询的结果进行组装。

 

Sqlsession运行总结

 

 

 

 

posted @ 2018-07-25 15:30  buptyuhanwen  阅读(145)  评论(0编辑  收藏  举报