深入理解mybatis

Mybatis组件时序图

SqlSessionFactoryBuilder类通过读取Configuration.xml文件的配置调用build()方法生成SqlSessionFactory对象。集成了spring的话,spring容器在启动的时候会就会加载好SqlSessionFacotry这对象也是调用这个类build()的方法。

SqlSession是当一个请求进来的时候SqlSessionFactory会通过openSession方法创建一个新的实例对象sqlSession 


一、配置

Configuration这是一个配置对象,存放的是Configuration.xml里面的我们对于mybatis的一些配置,项目初始化的时候加载
Environment是一个数据源配置配置对象,也是配置在Configuration.xml里面的Environment标签。项目初始化的时候就加载好了(我们用的是alibaba的druid数据源)



二、事务

结合图openSession方法其中的TransactionFactory是mybatis的事务管理(工厂模式)
mybatis的本身事务管理机制分成两种
    1、使用JDBC事务管理机,这种机制会生成一个JdbcTransaction对象有。也就是调用java.sql.Connection来进行管理
    2、使用容器的管理机制也就是ManagedTransaction这个对象来管理事务。这种方式程序本身是不会去 管理事务了,即使在程序中执行了commit和rollback也没用。因为程序本身不对事务进行管理了。这个事务管理交给容器
如果mybatis集成了spring 而是使用org.mybatis.spring包里面的SpringManagedTransaction来进行管理(spring容器进行事务管理)

三、sqlSession和Executor执行器

sqlSession默认实现类defaultSqlSession, 在这个对象中它执有configuration对象和executor对象。
configuration对象就是我们上面提到的一个配置对像,根据Configuration.xml配置文件而来的一个对象

查看DefaultSqlSession的源码,可以发现它所有的操作都通过executor对象在调用。其实sqlSession就像只是对外暴露的一个接口,而真正对数据的交互是由executor来进行操作的。sqlSession其实只是对Executor一个包装。
而Executor才是真正的工作者。Executor的实现类分别是以下三种,以下是它们的区别和它们的关系图

1.SimpleExecutor是mybatis默认的实现类。它的特性是每对数据进行一次交互会关闭掉statement
2.ReuseExecutor会对statement进行重复使用。对数据库操作执行完成之后会把statement放在一个map里面,key是执行的sql,value就是本次执行的statement对象。如果本次会话再次对数据进行操作。
那么这个执行器会根据sql去调用这个map里面statement去执行没有则创建并存放到map里同。而不是重新去实例化一个新的statement对象。
3.BatchExecutor支持批量操作

注:statement 就是java自带的jdbc的数据操作对象

以下是它们之间的类图(策略模式) 


四、缓存

CachingExexutor是mybatis二级缓存机制的体现,它也实现了Executor这个接口 (装饰者模式),
mybatis缓存机制分一级缓存和二级缓存,
1.一级缓存是session会话级,一次会话创建一个缓存对象这个缓存对象在本次会话是共享的,会话结束缓存对象也就销毁了,一次SqlSession会创建一个executor对象。executor对象会执有一个PerpetualCahce缓存对象。
这个缓存对象会将本次的查询结果集放到一个map的value里面。key是根据statementId、sql、param生成
2.二级缓存是application级别,所有会话都可以对这个缓存对象进行操作的。这个缓存是共享的。这个缓存级别粒度非常细。在开发过种中开发者可以自定义缓存实现方式,需要实现Cache接口。需要在maaper文件里面配置通过cache标签配置缓存。
也可以通过cach-ref标签引入别一个mapper里面定义的缓存

注:mybatis是缓存机制是先调用 二级缓存,如果不存在再去调用一级缓存。如果一级缓存也不存在。才会去数据库查。 



先看看SimpleExecutor执行器对一个数据库查询语句是怎么去实现的数据库查询的。首先它会创建一个jdbc statement对象


参数:
    MappedStatement:mapper文件里面sql配置信息
    object parameter: 动态sql语句的参数
    RowBounds: mybais自带的分页功能
    ResultHandler: sql语句返回的结果集处理器,比如我们mapper文件里面配置 resultMap , resultType结果集的处理
    BoundSql: sql语句及一些sql的简单信息,比如sql用几个 ?占位符,几个参数等一些信息。
五、StatementHandler处理器
以下是StatementHandler类图(策略模式) 



StatementHandler默认实现类是RoutingStatementHandler,以下是它的构造方法



statementType是配置在mapper.xml文件sql语句标签上的。   不写的话默认是PREPARED 


这三个StatementHandler。   分别是 statement、PreparedStatement、CallableStatement 
SimpleStatementHandler            

                                                               

PreparedStatementHandler                                                        

CallableStatementHandler



 以下是它们的区别

  1. 1Statement 每次执行sql语句,数据库都要执行sql语句的编译 ,最好用于仅执行一次查询并返回结果的情形,效率高于PreparedStatement.
  2.    注:根据这个statement特性。如果一条sql语句使用了这个statement来进行数据操作。那么mybatisSimpleStatementHandler是不会对参数进行处理的。它会默认认为你这条sql是没有参数的。不会调用mybatisParamerHandler来进行参数处理
  3. 2 PreparedStatement是预编译的,使用PreparedStatement有几个好处(mybatis默认是使用这个)
  4. a. 在执行可变参数的一条SQL时,PreparedStatementStatement的效率高,因为DBMS预编译一条SQL当然会比多次编译一条SQL的效率要高。
  5. b. 安全性好,有效防止Sql注入等问题。
  6. c.  对于多次重复执行的语句,使用PreparedStament效率会更高一点,并且在这种情况下也比较适合使用batch
  7. d.  代码的可读性和可维护性。
  8. 3CallableStatement接口扩展 PreparedStatement,用来调用存储过程,它提供了对输出和输入/输出参数的支持。CallableStatement 接口还具有对 PreparedStatement 接口提供的输入参数的支持。


六、ParamerHandler参数处理

    ParamerHandler的实现类只有一个DefaultParamerHandler,它的主要作用是对参数进行处理。基中mybatis   $ 和 # 这两个符号的处理方式不一样。
$符号处理方式: 会将值直接附到sql上面去,进行预编译,存在sql注入功击。当你不确认这个$符号绑定的那个对象的值时 ,  慎用!!!
#符号处理方式:会采用 ?这个占位符进行预编译。较为安全


七、ResultSetHandler结果集处理

    ResultSetHandler的主要功能是对结果集返回的一个封装。

SqlSession对象

有状态:有状态就是有数据存储功能。有状态对象(Stateful Bean),就是有实例变量的对象  ,可以保存数据,是非线程安全的。在不同方法调用间不保留任何状态。

无状态:无状态就是一次操作,不能保存数据。无状态对象(Stateless Bean),就是没有实例变量的对象  .不能保存数据,是不变类,是线程安全的。

因为mybatis的sqlSesssion 执有Exector对象。所以他是一个有状态的对象。官方给出的解释也是说这个对象是非线程安全的。

 但是mybatis对这个对象做了一个封装SqlSessionTemplate对象。SqlSessionTemplate对象主要是对sqlsession做了一个线程安全的实现。就是用java的动态代理。

 sqlsessionTemplate内部执有一个对sqlsession的一个代理对象。这个代理对象的实现就是生成一个新的sqlsession 这个sqlsession对象是从sqlsessionUtil.getsqlsession获取到的。

 这个类是在org.mybatis.spring包下面的是集成了spring的 。   它获取sqlsession的时候会先从spring中去获取。如果开启了spring的事务管理。那么你本次调用的sqlsession就会是你这次会话一个共用的sqlsession, 如果你没有开启事务的话,每次更新就会是一个新的sqlsession

 








猜你喜欢

转载自blog.csdn.net/geeksnow/article/details/52211879