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运行总结