• MyBatis框架的搭建以及使用教程


    MyBatis文章目录

    Mybatis框架的搭建以及使用教程

    目录

    MyBatis文章目录

    前言

    一、Mybatis框架搭建步骤

    第一步:准备工作

    1.下载并添加MyBatis依赖包

    2.创建数据库表结构

    3.创建实体类

    第二步:SQL映射文件

    第三步:核心配置文件

    第四步:日志文件

    第五步:创建测试类

    二、MyBatis核心对象

    使用步骤:

    三、MyBatis工具类

    四、MyBatis Mapper

    概述:Mapper映射器是 MyBatis 中最重要的文件,文件中包含一组 SQL 语句(例如查询、添加、删除、修改),这些语句称为映射语句或 SQL映射语句

    1.作用:

    2.实现方式:

    3.XML实现映射器

    4.select 标签:

    5.传递多个参数:

    6.区别:

    7.insert标签:

    【示例】

    8.主键(自动递增)回填:

    9.自定义主键:

    10.resultMap 元素:

    11.resultMap元素的构成:

    12.resultType和resultMap的区别:

    五、MyBatis 关联查询

    1.概述:

    2.一对一关联查询:

    3.多对多关联查询:

    六、MyBatis 动态SQL

    1.概述:

    2.if 标签:条件判断:

    3.choose标签:多重条件分支:

    4.where标签:处理查询条件:

    5.set标签:动态更新:

    示例

    6.foreach 标签:迭代遍历:

    7.#{}与${}的区别:

    七、MyBatis 批处理

    1.概述:

    2.使用动态SQL进行批量添加

    3.MyBatis BATCH模式:

    1. SqlSession的获取:

    2. SQL映射

    3. 批量执行

    八、MyBatis 缓存

    1.概述:

    2.一级缓存:

    3.二级缓存:

    4.二级缓存的执行流程:

    5.二级缓存的配置:

    总结



    前言

    MyBatis 是一个开源、轻量级的数据持久化框架,是 JDBC Hibernate 的替代方案。MyBatis 内部封装了 JDBC,简化了加载驱动、创建连接、创建 statement 等繁杂的过程,开发者只需要关注 SQL 语句本身。


    提示:以下是本篇文章正文内容,下面案例可供参考

    一、Mybatis框架搭建步骤

    第一步:准备工作

    1.下载并添加MyBatis依赖包

    官网地址https://github.com/mybatis/mybatis-3/releases

    上图中的 mybatis-3.5.10.jarMyBatis的核心包,mybatis-3.5.10.pdfMyBatis官方使用手册,lib 文件夹下的 jar 文件是 MyBatis的依赖包。

    我们需要将核心包mybatis-3.5.10.jarlib目录下的依赖包,以及MySQL的JDBC驱动包,全部添加至项目构建路径中。

    2.创建数据库表结构

    1. DROP TABLE IF EXISTS `website`;
    2. CREATE TABLE `website` (
    3. `id` int(11) NOT NULL AUTO_INCREMENT,
    4. `name` varchar(20) COLLATE utf8_unicode_ci NOT NULL,
    5. `url` varchar(30) COLLATE utf8_unicode_ci DEFAULT '',
    6. `age` tinyint(3) unsigned NOT NULL,
    7. `country` char(3) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
    8. `createtime` timestamp NULL DEFAULT NULL,
    9. PRIMARY KEY (`id`)
    10. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

    3.创建实体类

    src 目录下创建一个名为com.apesource.entity 的包,在该包中创建实体类 Website

    注意,在类中声明的属性名称与数据表 website 的字段名称,保持完全一致。

    1. import java.util.Date;
    2. public class Website {
    3. private int id;
    4. private String name;
    5. private String url;
    6. private int age;
    7. private String country;
    8. private Date createtime;
    9. @Override
    10. public String toString() {
    11. return "Website [id=" + id + ", name=" + name + ", url=" + url + ", age=" + age + ", country=" + country
    12. + ", createtime=" + createtime + "]";
    13. }
    14. }

    第二步:SQL映射文件

    src 目录下创建 com.apesource.mapper 包,在该包下创建映射文件 WebsiteMapper.xml

    1. "1.0" encoding="UTF-8"?>
    2. mapper
    3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    5. <mapper namespace="com.apesource.mapper.WebsiteMapper">
    6. <insert id="insertWebsite" parameterType="com.apesource.entity.Website">
    7. insert into website
    8. (name,url,age,country)
    9. values(#{name},#{url},#{age},#{country})
    10. insert>
    11. <select id="selectAllWebsite"
    12. resultType="com.apesource.entity.Website">
    13. select * from website
    14. select>
    15. mapper>

    元素是配置文件的根元素,它包含了 namespace属性,该属性值通常设置为“包名+SQL映射文件名”,用于指定唯一的命名空间。

    子元素 等节点进行SQL语句的映射配置。

  1. <select id="selectPerson" parameterType="int" resultType="hashmap">
  2. SELECT * FROM PERSON WHERE ID = #{id}
  3. select>
  4. <insert id="insertAuthor">
  5. insert into Author (id,username,password,email,bio)
  6. values (#{id},#{username},#{password},#{email},#{bio})
  7. insert>
  8. <update id="updateAuthor">
  9. update Author set
  10. username = #{username},
  11. password = #{password},
  12. email = #{email},
  13. bio = #{bio}
  14. where id = #{id}
  15. update>
  16. <delete id="deleteAuthor">
  17. delete from Author where id = #{id}
  18. delete>

通过注解的方式实现:在映射器接口中,使用@select@insert等注解进行SQL语句的映射配置

  1. public interface UserMapper{
  2. @Insert("insert into user(id,name) values(#{id},#{name})")
  3. public int insert(User user);
  4. @Select("Select * from user")
  5. @Results({
  6. @Result(id = true, column = "id", property = "id"),
  7. @Result(column = "name", property = "name"),
  8. @Result(column = "sex", property = "sex"),
  9. @Result(column = "age", property = "age")
  10. })
  11. List queryAllUser();
  12. }

SQL 语句存在动态 SQL或者比较复杂,使用注解写在Java 文件里可读性差,且增加了维护的成本。所以一般建议使用 XML 文件配置的方式,避免重复编写 SQL 语句。

3.XML实现映射器

XML 定义映射器分为两个部分:接口和XML

首先,定义一个映射器接口 WebsiteMapper

  1. package com.apesource.mapper;
  2. public interface WebsiteMapper {
  3. public List selectAllWebsite();
  4. }

然后,定义一个XML映射文件WebsiteMapper.xml

  1. "1.0" encoding="UTF-8"?>
  2. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  3. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  4. "com.apesource.mapper.WebsiteMapper">

下面对上述 XML 文件进行讲解。

  • namespace用来定义命名空间,该命名空间和定义接口的全限定名一致。
  • "selectWebsiteListLikeName"
  • resultType="com.apesource.entity.Website"
  • parameterType="string">
  • SELECT id,NAME,url FROM website WHERE NAME LIKE CONCAT ('%',#{name},'%')
  • 以上是一个 id selectWebsiteListLikeName的映射语句,参数类型为 string,返回结果类型为 Website。执行 SQL 语句时可以定义参数,参数可以是一个简单的参数类型,例如 intfloatString;也可以是一个复杂的参数类型,例如 JavaBeanMap 等。MyBatis 提供了强大的映射规则,执行 SQL 后,MyBatis 会将结果集自动映射到指定的 JavaBean

    参数的传递使用#{参数名},相当于告诉 MyBatis 生成 PreparedStatement参数。对于 JDBC,该参数会被标识为“?”。以上 SQL 语句如果使用 JDBC 实现,实现代码如下:

    1. String sql = "SELECT id,NAME,url FROM website WHERE NAME LIKE CONCAT ('%',?,'%')";
    2. PreparedStatement ps = conn.prepareStatement(sql);
    3. ps.setString(1,name);

    5.传递多个参数:

    1. 使用Map传递参数
    2. 使用注解传递参数
    3. 使用JavaBean传递参数

    6.区别:

    以上 3 种方式的区别如下:

    7.insert标签:

    MyBatisinsert 标签用来定义插入语句,执行插入操作。当 MyBatis 执行完一条插入语句后,就会返回其影响数据库的行数。

    【示例】

    WebsiteMapper.xml映射文件中,增加节点,插入语句,代码如下:

    1. "insertNewWebsite" parameterType="com.apesource.entity.Website">
    2. insert into website(name,url,age)values(#{name},#{url},#{age})
    1. WebsiteMapper 接口中定义一个 insertNewWebsite() 方法,代码如下:
    public int insertNewWebsite(Website website);

    8.主键(自动递增)回填:

    在某些业务场景下,我们可能需要将这个刚刚生成的主键回填到请求对象(原本不包含主键信息的请求对象)中,供其他业务使用。此时,我们就可以通过在 标签中添加 keyPropertyuseGeneratedKeys 属性,来实现该功能。

    1. <insert id="insertNewWebsite"
    2. parameterType="com.apesource.entity.Website"
    3. useGeneratedKeys="true"
    4. keyProperty="id">
    5. insert into website(name,url,age)values(#{name},#{url},#{age})
    6. insert>

    9.自定义主键:

    在某些业务场景下,我们可能需要将这个刚刚生成的主键回填到请求对象(原本不包含主键信息的请求对象)中,供其他业务使用。此时,我们就可以通过在 标签中添加 keyPropertyuseGeneratedKeys 属性,来实现该功能

    1. <insert id="insertNewWebsite"
    2. parameterType="com.apesource.entity.Website"
    3. useGeneratedKeys="true"
    4. keyProperty="id">
    5. insert into website(name,url,age)values(#{name},#{url},#{age})
    6. insert>

    10.resultMap 元素:

    resultMapMyBatis 中最复杂的元素,主要用于解决实体类属性名与数据库表中字段名不一致的情况,可以将查询结果映射成实体对象。

    11.resultMap元素的构成:

    标签中属性说明如下:

    12.resultType和resultMap的区别:

    MyBatis 的每一个查询映射的返回类型都是 resultMap,只是当我们提供的返回类型是 resultType 时,MyBatis 会自动把对应的值赋给 resultType 所指定对象的属性,而当我们提供的返回类型是 resultMap 时,MyBatis 会将数据库中的列数据复制到对象的相应属性上,可用于复制查询。

    需要注意的是,resultMap resultType 不能同时使用。

    五、MyBatis 关联查询

    1.概述:

    关联关系是一个数据库实体的概念,有 3 种级联关系,分别是一对一级联、一对多级联以及多对多级联。例如,一个角色可以分配给多个用户,也可以只分配给一个用户。大部分场景下,我们都需要获取角色信息和用户信息,所以会经常遇见以下 SQL。

    1. SELECT r.*,u.* FROM t_role r
    2. INNER JOIN t_user_role ur ON r.id = ur.id
    3. INNER JOIN t_user u ON ur.user_id = u.id
    4. WHERE r.id = #{id}

    在级联中存在 3 种对应关系。

    2.一对一关联查询:

    一对一级联关系在现实生活中是十分常见的,例如:一个学生基本信息对应一个学籍档案。

    MyBatis 中,通过 元素的子元素 处理一对一级联关系。示例代码如下:

    1. <association property="studentCard" column="cardId"
    2. javaType="com.apesource.entity.StudentCard"
    3. select="com.apesource.mapper.StudentCardMapper.selectStuCardById" />

    元素中通常使用以下属性。

    一对一关联查询可采用以下两种方式:

    3.多对多关联查询:

    实际应用中,由于多对多的关系比较复杂,会增加理解和关联的复杂度,所以应用较少。MyBatis没有实现多对多级联,推荐通过两个一对多级联替换多对多级联,以降低关系的复杂度,简化程序。

    例如,一个订单可以有多种商品,一种商品可以对应多个订单,订单与商品就是多对多的级联关系。可以使用一个中间表(订单记录表)将多对多级联转换成两个一对多的关系。

    六、MyBatis 动态SQL

    1.概述:

    动态 SQL 是 MyBatis的强大特性之一。在 JDBC 或其它类似的框架中,开发人员通常需要手动拼接 SQL 语句。根据不同的条件拼接 SQL 语句是一件极其痛苦的工作。例如,拼接时要确保添加了必要的空格,还要注意去掉列表最后一个列名的逗号。而动态 SQL 恰好解决了这一问题,可以根据场景动态的构建查询。
    动态 SQL只有几个基本元素,大量的判断都可以在 MyBatis的映射 XML文件里配置,以达到许多需要大量代码才能实现的功能。所以,使用动态 SQL,可以 大大减少了编写代码的工作量,更体现了 MyBatis 的灵活性、高度可配置性和可维护性。

    MyBatis 的动态 SQL 包括以下几种元素,如下所示:

    元素

    作用

    备注

    if

    判断语句

    单条件分支判断

    choose(when、otherwise)

    相当于 Java 中的 switch case 语句

    多条件分支判断

    where
    set

    辅助元素

    用于处理一些SQL拼装问题

    foreach

    循环语句

    在in语句等列举条件常用

    2.if 标签:条件判断:

    MyBatisif 类似于 Java 中的 if 语句,是 MyBatis中最常用的判断语句。使用 if 标签可以节省许多拼接 SQL 的工作,把精力集中在 XML的维护上。

    if 语句使用方法简单,常常与 test 属性联合使用。语法如下:

    1. <if test="判断条件">
    2. SQL语句
    3. if>

    3.choose标签:多重条件分支:

    有时候,我们不想使用所有的条件,而只是想从多个条件中选择一个使用。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。

    MyBatis 中动态语句 类似于 Java 中的 switch-case-default多重分支条件语句。由于 MyBatis 并没有为 if 提供对应的 else 标签,如果想要达到...... 的效果,可以借助 来实现。

    动态语句 语法如下:

    1. <choose>
    2. <when test="判断条件1">
    3. SQL语句1
    4. <when test="判断条件2">
    5. SQL语句2
    6. <when test="判断条件3">
    7. SQL语句3
    8. <otherwise>
    9. SQL语句4
    10. otherwise>
    11. choose>

    标签按顺序判断其内部 标签中的判断条件是否成立,如果有一个成立,则执行相应的 SQL 语句, 执行结束;如果都不成立,则执行 中的 SQL 语句。这类似于 Javaswitch 语句,switchcase 则为 default

    4.where标签:处理查询条件:

    如果在多重if条件的查询过程中,如果在where条件中,没有设置条件1=1那么可能就会变成下面这样一条错误的语句:

    SELECT id,name,url,age,country FROM website AND name LIKE CONCAT('%',#{name},'%')

    显然以上语句会出现 SQL 语法异常,但加入“1=1”这样的条件又非常奇怪,所以 MyBatis 提供了 where 标签。主要用来简化 SQL 语句中的条件判断,可以自动处理 AND/OR 条件,语法如下:

    1. <where>
    2. <if test="判断条件">
    3. AND/OR ...
    4. </if>
    5. </where>

    if 语句中判断条件为 true 时,where 关键字才会加入到组装的 SQL 里面,否则就不加入。where 会检索语句,它会将 where 后的第一个 SQL 条件语句的 AND 或者 OR 关键词去掉。

    5.set标签:动态更新:

    Mybatis 中,update 语句可以使用 set 标签动态更新列。set 标签可以为 SQL 语句动态的添加 set 关键字,剔除追加到条件末尾多余的逗号。

    示例

    要求:根据 id 修改网站名称或者网址等信息

    1. <update id="updateWebsite" parameterType="com.apesource.entity.Website">
    2. UPDATE website
    3. <set>
    4. <if test="name !=null and name!=''">name=#{name},if>
    5. <if test="url !=null and url!=''">url=#{url},if>
    6. <if test="age !=null and age!=''">age=#{age},if>
    7. set>
    8. where id=#{id}
    9. update>

    6.foreach 标签:迭代遍历:

    SQL 语句中含有 in关键字进行列表值匹配时,需要迭代条件集合来生成的情况,可以使用 foreach来实现 SQL 条件的迭代。

    Mybatis foreach 标签用于循环语句,它很好的支持了数据和 Listset接口的集合,并对此提供遍历的功能。语法格式如下:

    1. <foreach item="item" index="index" collection="list|array|map key" open="(" separator="," close=")">
    2. 参数值
    3. foreach>

    foreach 标签主要有以下属性,说明如下。

    使用 foreach 标签时, collection属性是必选,但在不同情况下该属性的值是不一样的,主要有以下 3种情况:

    7.#{}${}的区别:

    默认情况下,使用 #{}参数语法时,MyBatis会创建 PreparedStatement参数占位符,并通过?占位符安全地设置参数。 这样做更安全,更迅速,通常也是首选做法,不过有时你就是想直接在 SQL 语句中直接插入一个不转义的字符串。 比如 ORDER BY 子句,这时候你可以:ORDER BY ${columnName},这个时候${}将直接在SQL语句中进行字符串的拼接。
    具体区别点总结如下:
    1使用#{}会产生1个?占位符,并使用PreparedStatement进行处理。而${}则进行的是字符串的拼接。
    2使用#{}可以预防SQL注入,而${}无法防止SQL注入。
    3${}一般用于在SQL中拼接数据库表名、视图或关键字,例如动态使用order by 进行排序时,就需要使用${}来拼接排序字段名称和排序规则。

    七、MyBatis 批处理

    1.概述:

    批处理是 JDBC编程中的一种优化手段。JDBC 在执行 SQL语句时,会将 SQL +参数值,利用JDBC驱动包,在底层使用基于TCP协议的网络请求将SQL语句发送到数据库。如果SQL语句数量较多,一次执行一条 SQL 语句,一方面会减小请求包的有效负载,另一个方面会增加耗费在网络通信上的时间,与执行时间的开销必然加大,影响程序执行的效果与性能。

    通过批处理的方式,我们就可以在 JDBC 客户端缓存多条SQL 语句,然后将多条SQL 语句以打包的方式,批量发送到数据库执行,这样就可以有效地降低上述两方面的损耗,从而提高系统性能。

    可以通过show VARIABLES LIKE 'max_allowed_packet';查看MySQL通信时的最大数据包容量。

    假设max_allowed_packet的值为33554432字节,则33554432字节 = 32M,也就是规定大小不能超过32M。根据实践经验,批处理最好设置为max_allowed_packet50%

    在结合MyBatis框架进行批处理操作时,通常使用两种方式:

    1. 使用动态SQL进行批量添加。
    2. 使用MyBatis BATCH模式进行批量添加

    2.使用动态SQL进行批量添加

    该方式基于SQL语句中的批量添加数据的语法形式:

    1. INSERT INTO 表名(字段1,字段2,字段3)
    2. VALUES(值1,值1,值1,),
    3. (值2,值2,值2,),
    4. (值3,值3,值3,),
    5. (值4,值4,值4,),
    6. (值5,值5,值5,);

    按照该语法形式,则SQL映射接口中insertNewWebsiteBatch方法如下所示:

    1. public interface WebsiteMapper {
    2. // 批量添加网站信息
    3. public int insertNewWebsiteBatch(List websiteList);
    4. }

    SQL映射文件中的配置如下所示:

    1. <insert id="insertNewWebsiteBatch">
    2. INSERT INTO website (name, url, age, country, createtime)
    3. VALUES
    4. <foreach collection="list" item="website" separator=",">
    5. (#{website.name},#{website.url},#{website.age},#{website.country},now())
    6. foreach>
    7. insert>

    测试:

    1. try (SqlSession sqlSession = MyBatisUtils.getSqlSession();) {
    2. WebsiteMapper websiteMapper = sqlSession.getMapper(WebsiteMapper.class);
    3. int r = websiteMapper.insertNewWebsiteBatch(websiteList);
    4. sqlSession.commit();
    5. System.out.println("影响行数:" + r);
    6. }

    适用场景:该种方式适合数据量较小的情况下,一次性将SQL语句全部发送给MySQL执行。如果数据量较大,为了能配合max_allowed_packet参数要求的数据包容量,则需要在批处理的基础上,分批执行SQL语句。

    3.MyBatis BATCH模式:

    该方式基于MyBatisBatchExecutor对SQL语句进行批处理执行,由于MySQL的批处理执行机制要求,必须在连接字符串中添加参数rewriteBatchedStatements=true,才可以真正开启批处理机制。

    1. SqlSession的获取:

    由于获取的SqlSession用于执行批处理,所以获取方式比之前的普通执行方式有所不同,必须设置SqlSessionFactoryExecutorType,这样在创建SqlSession时,内置的ExecutorBatchExecutor

    1. if (ExecutorType.BATCH == executorType) {
    2. executor = new BatchExecutor(this, transaction);
    3. }

    所以,执行批处理时,创建SqlSession的代码如下所示:

    SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH, false);

    工具类MyBatisUtils封装代码如下:

    1. public class MyBatisUtils {
    2. private static SqlSessionFactory factory = null;
    3. static {
    4. try {
    5. SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
    6. factory = builder.build(Resources.getResourceAsStream("mybatis-config.xml"));
    7. } catch (IOException e) {
    8. e.printStackTrace();
    9. }
    10. }
    11. public static SqlSession getSqlSession() {
    12. SqlSession session = null;
    13. if(factory != null ) {
    14. // 创建普通执行模式的SqlSession
    15. // 该模式下的执行器类型默认为ExecutorType.SIMPLE
    16. // 所以,使用的Executor执行器对象类型为SimpleExecutor
    17. session = factory.openSession();
    18. }
    19. return session;
    20. }
    21. public static SqlSession getBatchSqlSession() {
    22. SqlSession session = null;
    23. if(factory != null ) {
    24. // 创建批处理模式的SqlSession
    25. // 该模式下的执行器类型默认为ExecutorType.BATCH
    26. // 所以,使用的Executor执行器对象类型为BatchExecutor
    27. session = factory.openSession(ExecutorType.BATCH);
    28. }
    29. return session;
    30. }
    31. }

    2. SQL映射

    1. <insert id="insertNewWebsite"
    2. parameterType="com.apesource.entity.Website">
    3. insert into
    4. website(name,url,age,country,createtime)values(#{name},#{url},#{age},#{country},now())
    5. </insert>
    1. // 添加新网站信息
    2. public int insertNewWebsite(Website site);

    3. 批量执行

    1. try (SqlSession sqlSession = MyBatisUtils.getBatchSqlSession();) {
    2. WebsiteMapper websiteMapper = sqlSession.getMapper(WebsiteMapper.class);
    3. // 添加5w条记录
    4. for (int i = 0; i < 50000; i++) {
    5. int r = websiteMapper.insertNewWebsite(new Website());
    6. // 每1000条执行1次批处理
    7. if (i != 0 && i % 1000 == 0) {
    8. sqlSession.commit();
    9. }
    10. }
    11. sqlSession.commit();
    12. }

    1000条执行1次批处理时,如果执行sqlSession.commit()则代表本次批处理的中的所有SQL语句全部通过Executor一次性发送给MySQL执行,并清除本地缓存与操作。

    八、MyBatis 缓存

    1.概述:

    缓存可以将数据保存在内存中,是互联网系统常常用到的。目前流行的缓存服务器有 MongoDBRedisEhcache 等。缓存是在计算机内存上保存的数据,读取时无需再从磁盘读入,因此具备快速读取和使用的特点。
    和大多数持久化框架一样,MyBatis 提供了一级缓存和二级缓存的支持。默认情况下,MyBatis只开启一级缓存。

    2.一级缓存:

    一级缓存是基于 PerpetualCache(MyBatis自带)的 HashMap 本地缓存,作用范围为 SqlSession 域内。当 session flush(刷新)或者 close(关闭)之后,该 session 中所有的 cache(缓存)就会被清空。

    在参数和 SQL 完全一样的情况下,我们使用同一个 SqlSession 对象调用同一个 mapper的方法,往往只执行一次 SQL。因为使用 SqlSession 第一次查询后,MyBatis会将其放在缓存中,再次查询时,如果没有刷新,并且缓存没有超时的情况下,SqlSession会取出当前缓存的数据,而不会再次发送 SQL到数据库。

    由于 SqlSession 是相互隔离的,所以如果你使用不同的 SqlSession 对象,即使调用相同的 Mapper、参数和方法,MyBatis还是会再次发送 SQL 到数据库执行,返回结果。

    3.二级缓存:

    二级缓存是全局缓存,作用域超出 SqlSession范围之外,可以被所有 SqlSession共享。也可以理解为是SqlSessionFactory范围的缓存。

    二级缓存与一级缓存原理相同,默认也是采用 PerpetualCache,使用HashMap作为存储,不同在于其存储作用域为Mapper ( Namespace)范围,并且可自定义存储源,例如Ehcache等第三方中间件。作用域为 namespance 是指对该 namespance对应的配置文件中所有的 select 操作结果都缓存,这样不同线程之间就可以共用二级缓存。

    4.二级缓存的执行流程:

    1. 当一个sqlseesion执行了一次select后,关闭此session的时候,会将查询结果缓存到二级缓存
    2. 当另一个sqlsession执行select时,首先会在一级缓存中找,如果没找到,就回去二级缓存中找,找到了就返回,就不用去数据库了,从而减少了数据库压力提高了性能。

    5.二级缓存的配置:

    1. MyBatis 的全局缓存配置需要在 mybatis-config.xmlsettings 元素中设置,代码如下:
    1. <settings>
    2.   <setting name="cacheEnabled" value="true" />
    3. settings>
    1. mapperSQL映射文件(如 WebsiteMapper.xml)中设置缓存,默认不开启缓存。需要注意的是,二级缓存的作用域是针对 mappernamescape,只有再次在同一个 namescape内(com.apesource.mapper.WebsiteMapper)的查询才能共享这个缓存,代码如下:
    1. <mapper namescape="com.apesource.mapper.WebsiteMapper">
    2. <cache
    3. eviction="FIFO"
    4. flushInterval="60000"
    5. size="512"
    6. readOnly="true" />
    7. ...
    8. mapper>

    属性

    说明

    eviction

    代表的是缓存回收策略,目前 MyBatis 提供以下策略。

    • LRU:使用较少,移除最长时间不用的对象;
    • FIFO:先进先出,按对象进入缓存的顺序来移除它们;
    • SOFT:软引用,移除基于垃圾回收器状态和软引用规则的对象;
    • WEAK:弱引用,更积极地移除基于垃圾收集器状态和弱引用规则的对象。

    flushInterval

    刷新间隔时间,单位为毫秒,这里配置的是 100 秒刷新,如果省略该配置,那么只有当 SQL 被执行的时候才会刷新缓存。

    size

    引用数目,正整数,代表缓存最多可以存储多少个对象,不宜设置过大。设置过大会导致内存溢出。这里配置的是 1024 个对象。

    readOnly

    只读,默认值为 false,意味着缓存数据只能读取而不能修改,这样设置的好处是可以快速读取缓存,缺点是没有办法修改缓存。

    1. 在 SQL映射文件配置支持 cache后,如果需要对个别查询进行调整,可以单独设置 cache是否启用,代码如下:
    1. <select id="selectWebsiteList" resultType="com.apesource.entity.Website" usecache="false">
    2. ...
    3. select>

    总结

            以上就是今天要讲的内容,本文仅仅简单介绍了MyBatis的使用,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Ordinary Java Object,普通的 Java对象)映射成数据库中的记录。

  • 相关阅读:
    计算机网络——23网络层导论
    联邦学习中的推理攻击
    spring boot配置文件中 Duration解析
    #案例:切换标签页/切换窗口!
    计算机视觉40例之案例05物体计数
    如何理解springboot的自动注入
    17. 线性代数 - 矩阵的逆
    十四、InnoDB的ACID事务
    美团二面算法 之 串联所有单词的子串[困难]
    七夕?程序员不存在的~
  • 原文地址:https://blog.csdn.net/qq_17845335/article/details/126351453