MyBatis篇

半自动的ORM持久层框架,封装了JDBC操作数据库的过程,让开发者更加关注sql本身。

  • 持久化:把内存中的数据同步保存到数据库(如关系数据库)或永久存储设备(如硬盘、磁带等)中。

  • 持久层:一个逻辑层面,专注于实现数据持久化的一个相对独立的领域。

1、执行流程

  1. 获取MyBatis配置文件Resources获取加载全局配置文件,得到一个流对象。

  2. 构建SqlSessionFactory构造会话工厂:将流对象传递到SqlSessionFactoryBuilder构建者对象build()方法中,该方法创建了XMLConfigBuilder解析器对象,解析传递进来的流对象,解析完成后,解析的内容会保存在Configuration对象中,最终通过Configuration对象获得了实现了SqlSessionFactory接口DefaultSqlSessionFactory对象

  3. 创建Transaction事务管理器&Executor核心执行器:由SqlSessionFactory调用openSession()方法,在方法过程中,TransactionFactory生成Transaction事务管理器对象, 并且还创建了核心执行器Executor对象。基于这些条件,最终创建了

  4. 创建SqlSession会话对象:通过SqlSessionFactory调用openSession()方法,最后创建出实现SqlSession接口DefaultSqlSession对象,该对象中包含了执行SQL语句的所有方法。之后,通过SqlSession对象执行相应的操作,如果执行成功,调用commit()方法提交事务;如果失败,调用rollback()方法事务回滚。最后,调用close()方法关闭session资源。

2、四大组件-生命周期和作用域

2.1、SqlSessionFactoryBuilder

SqlSessionFactoryBuilder的作用在于创建 SqlSessionFactory,创建成功后,SqlSessionFactoryBuilder 就失去了作用。

  • 作用域:局部作用域。

2.2、SqlSessionFactory

SqlSessionFactory可以被认为是一个数据库连接池,它的作用是创建SqlSession接口对象。一旦被创建就应该在应用的运行期间一直存在,不要重复创建多次。简单的就是使用单例模式或者静态单例模式。

  • 作用域:应用作用域。

2.3、SqlSession

SqlSession相当于一个数据库连接 (Connection)对象,可以在一个事务里面执行多条 SQL,然后通过它的 commit、 rollback 等方法,提交或者回滚事务。存活在一个业务请求中,处理完整个请求后,关闭这条连接。确保每次都能执行关闭操作,应该把这个关闭操作放到 finally 块中。SqlSession的实例是线程不安全的。

  • 作用域:请求或方法作用域。

2.4、Mapper(映射器)

Mapper是一个接口,它由SqlSession所创建,所以它的生命周期应该小于等于SqlSession的生命周期。

作用域:方法作用域。

3、配置文件结构

4、缓存

目的就是提升查询的效率和减少数据库的压力。MyBatis提供了一级缓存和二级缓存,并且预留了集成第三方缓存的接口。

缓存清除策略(默认的清除策略是 LRU):

  • LRU – 最近最少使用:移除最长时间不被使用的对象。

  • FIFO – 先进先出:按对象进入缓存的顺序来移除它们。

  • SOFT – 软引用:基于垃圾回收器状态和软引用规则移除对象。

  • WEAK – 弱引用:更积极地基于垃圾收集器状态和弱引用规则移除对象。

4.1、一级缓存

一级缓存也叫本地缓存,MyBatis 的一级缓存是在会话(SqlSession)层面进行缓存的。MyBatis 的一级缓存是默认开启的,不需要任何的配置。

在同一个会话里面,多次执行相同的SQL 语句,会直接从内存取到缓存的结果,不会再发送SQL 到数据库。但是不同的会话里面,即使执行的SQL 一模一样(通过一个Mapper 的同一个方法的相同参数调用),也不能使用到一级缓存。

4.1.1、生命周期

  1. MyBatis在开启一个数据库会话时,会 创建一个新的SqlSession对象,SqlSession对象中会有一个新的Executor对象,Executor对象中持有一个新的PerpetualCache对象;当会话结束时,SqlSession对象及其内部的Executor对象还有PerpetualCache对象也一并释放掉。

  2. 如果SqlSession调用了close()方法,会释放掉一级缓存PerpetualCache对象,一级缓存将不可用;

  3. 如果SqlSession调用了clearCache(),会清空PerpetualCache对象中的数据,但是该对象仍可使用;

  4. SqlSession中执行了任何一个update操作(update()、delete()、insert()) ,都会清空PerpetualCache对象的数据,但是该对象可以继续使用;

4.1.2、执行流程

  1. 对于某个查询,根据statementId,params,rowBounds来构建一个key值,根据这个key值去缓存Cache中取出对应的key值存储的缓存结果

  2. 判断从Cache中根据特定的key值取的数据数据是否为空,即是否命中;

  3. 如果命中,则直接将缓存结果返回;

  4. 如果没命中:

    1. 去数据库中查询数据,得到查询结果;

    2. 将key和查询到的结果分别作为key,value对存储到Cache中;

    3. 将查询结果返回;

  5. 判断是否是STATEMENT级别缓存,如果是,则清除缓存

4.1.3、级别

  • session级别:在同一个sqlSession内,对同样的查询将不再查询数据库,直接从缓存中。

  • statement级别:每次查询结束都会清掉一级缓存。

4.2、二级缓存

二级缓存是用来解决一级缓存不能跨会话共享的问题的,范围是namespace级别的,可以被多个SqlSession共享(只要是同一个接口里面的相同方法,都可以共享),生命周期和应用同步。如果你的MyBatis使用了二级缓存,并且你的Mapper和select语句也配置使用了二级缓存,那么在执行select查询的时候,MyBatis会先从二级缓存中取输入,其次才是一级缓存,即MyBatis查询数据的顺序是:二级缓存 —> 一级缓存 —> 数据库。

4.2.1、开启方法

第一步:配置 mybatis.configuration.cache-enabled=true,只要没有显式地设置cacheEnabled=false,都会用CachingExecutor装饰基本的执行器。

第二步:在Mapper.xml 中配置<cache/>标签:

 <cache type="org.apache.ibatis.cache.impl.PerpetualCache"
     size="1024"
 eviction="LRU"
 flushInterval="120000"
 readOnly="false"/>

5、SQL防注入

  • ${}(直处理):取值以后再去编译SQL语句,是直接的字符串拼接。

  • #{}(预处理):编译SQL语句后取值,预处理?的方式。

posted @ 2022-02-17 21:09  是老胡啊  阅读(30)  评论(0)    收藏  举报