Mybatis学习笔记,包含mybatis基本使用、关系映射、动态SQL、分页插件等等

😀😀😀创作不易,各位看官点赞收藏.

MyBatis 学习笔记

简介:MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。简单来说,mybatis就是用来操作数据库的,可以使程序猿更加容易书写 dao 层。

1、Mybatis Demo 程序

搭建环境:导入依赖、创建数据库表user(id,name,address)

<!--    junit-->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.11</version>
</dependency>
<!--    mybatis-->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.4.6</version>
</dependency>
<!--    数据库连接-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.21</version>
</dependency>
<!--      log4j-->
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.12</version>
</dependency>

编写配置文件:mybatis-config.xml,XML 配置文件中包含了对 MyBatis 系统的核心设置,包括获取数据库连接实例的数据源(DataSource)以及决定事务作用域和控制方式的事务管理器(TransactionManager)。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--mybatis的主配置文件-->
<configuration>
    <!-- 数据库配置环境-->
    <!-- default和下面的id名称要一样,默认使用,可以定义多个环境-->
    <environments default="mysql">
        <!-- 配置mysql的环境-->
        <environment id="mysql">
            <!-- 配置事务类型为jdbc-->
            <transactionManager type="JDBC"/>
            <!--   配置数据池连接源-->
            <!--   type有三种类型
                        1、POOLED是使用数据库连接池的类型
                        2、UNPOOLED是不适用数据库连接池的类型
                        3、JNDI是JNDI类型的数据源 JndiDataSource
             -->
            <dataSource type="POOLED">
                <!-- 配置数据库的4个基本信息-->
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql:///mybatis?characterEncoding=utf-8&amp;serverTimezone=UTC"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
    <!-- 引入映射文件-->
    <mappers>
        <mapper resource="mapper/UserMapper.xml"/>
    </mappers>
</configuration>

编写 Mapper 接口:

public interface UserMapper {
    // 查询所有的用户
    List<User> findAllUser();
}

编写 mapper.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace会绑定一个mapper接口,可以理解为实现这个接口,必须写全限定类名-->
<mapper namespace="com.jx.app.mybatis.mapper.UserMapper">
    <!--   id是接口中的方法名称,resultType是实体的全限定类名,标签体中写sql语句-->
    <select id="findAllUser" resultType="com.jx.app.mybatis.entity.User">
        select * from user
    </select>
</mapper>

编写 Mybatis 工具类:

public class MybatisUtils {
    // 成员变量
    private static SqlSessionFactory sqlSessionFactory;
    // 静态代码初始化
    static {
        try {
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    // 获取sqlSession
    public static SqlSession getSqlSession(){
        return sqlSessionFactory.openSession();
    }
}

测试查询结果:

@Test
public void test(){
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    List<User> users = mapper.findAllUser();
    System.out.println(users);
}

2、Mybatis 核心配置文件

environments:配置数据库连接配置环境。

<!-- default和下面的id名称要一样,默认使用,可以定义多个环境-->
<environments default="mysql">
    <!-- 配置mysql的环境,id是唯一标识不能重复-->
    <environment id="mysql">
        <!-- 配置事务管理方式:JDBC(原生事务)、MANAGED()-->
        <transactionManager type="JDBC"/>
        <!--   配置数据池连接源-->
        <!--   type有三种类型
                        1、POOLED是使用数据库连接池的类型
                        2、UNPOOLED是不适用数据库连接池的类型
                        3、JNDI使用上下文的数据源
         -->
        <dataSource type="POOLED">
            <!-- 配置数据库的4个基本信息-->
            <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql:///mybatis?characterEncoding=utf-8&amp;serverTimezone=UTC"/>
            <property name="username" value="root"/>
            <property name="password" value="123456"/>
        </dataSource>
    </environment>
</environments>

propertes:可以引入 properties 文件,然后通过某种方式去访问文件中的值。

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql:///mybatis?characterEncoding=utf-8&amp;serverTimezone=UTC
username=root
password=123456
<!-- 引入文件,然后可以在下面通过 ${key值} 获取对应的value-->
<properties resource="jdbc.properties"/>

settings:Mybatis 的全局配置,还有很多配置,可以去官网上查看。

<settings>
    <!-- 字段名与属性名驼峰命名映射:user_name == userName-->
    <setting name="mapUnderscoreToCamelCase" value="true"/>
    <!-- 指定 mybatis 中的日志输出-->
    <setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>

typeAliases:取别名标签,给实体类取一个别名,在映射结果时就可以使用别名就不再使用全限定类名。

<typeAliases>
    <!-- 在编写 mapper 映射文件时就可以使用 User 来代替这个全限定类名,不设置 alias 别名就是类名-->
    <typeAlias type="com.jx.app.mybatis.entity.User" alias="User"/>
    
    <!-- 把指定包下的所有类都起别名,别名都是类名-->
    <package name="com.jx.app.mybatis.entity"/>
</typeAliases>

mappers:引入 mapper 映射文件。

<!-- 引入映射文件-->
<mappers>
    <!-- 需要引入 mapper 文件存放在 resources 目录下-->
    <mapper resource="mapper/UserMapper.xml"/>

    <!-- 通过包名进行引入:1、mapper 文件名需要与接口一样,2、mapper 存放的目录结构也必须和接口保持一致-->
    <package name="com.jx.app.mybatis.mapper"/>
</mappers>

3、Mybatis Mapper 传参映射

​ 在 mapper 映射文件获取接口的参数有两种方式,${}#{}

  • ${}: 本质是字符串拼接,将参数与 SQL 语句进行简单拼接,这种方式可能存在 SQL 注入问题,使用这种方式需要注意字符串的单引号拼接。
  • #{}:本质是占位符方式来拼接 SQL,自动给参数加上单引号,这种方式防止 SQL 注入问题。

单个字面量参数:

// 参数 name 是单个字面量
User getUserByName(String name);
<select id="getUserByName" resultType="com.jx.app.mybatis.entity.User">
    SELECT *
    FROM user u
    WHERE u.user_name = #{name} 
    <!-- name参数需要和接口参数名保持一致-->
</select>

多个字面量参数:

// 存在多个参数
User getUser(String id, String name);
<!-- 如果存在多个参数,那么 mybatis 会把参数存储在一个 map 中,key:[arg0,arg1...,param1,param2...] 
     可以通过对应的键获取参数值,但是不能通过参数名去获取,这两种 key 可以混用,顺序就是指定的下标
-->
<select id="getUser" resultType="com.jx.app.mybatis.entity.User">
    SELECT *
    FROM user u
    <!-- WHERE u.id = #{arg0} AND u.user_name = #{arg1}-->
    WHERE u.id = #{param1} AND u.user_name = #{param2}
</select>

map 传参:

// 参数是一个map
User getUserByMap(Map<String,String> map);
<!-- 参数是一个 map,可以直接根据 key 获取对应的值-->
<select id="getUserByMap" resultType="com.jx.app.mybatis.entity.User">
    SELECT *
    FROM user u
    WHERE u.id = #{id} AND u.user_name = #{username}
</select>

实体类传参:

// 参数是一个是实体类
int insert(User user);
<!-- 参数是实体类,可以通过类的属性名获取对应的属性值-->
<insert id="insert">
    INSERT INTO user values(null,#{userName},#{password},#{money})
</insert>

@param 注解:可以命名参数,标识参数后依然后把参数放入 map 中,可以通过命名参数的 key 来获取参数值。

// @Param 将参数进行取别名命名
User getUser(@Param("id") String id, @Param("name") String name);
<!-- 使用 @param 注解后可以直接使用对应的命名 key 获取对应的值-->
<select id="getUser" resultType="com.jx.app.mybatis.entity.User">
    SELECT *
    FROM user u
    WHERE u.id = #{id} AND u.user_name = #{name}
</select>

4、Mybatis 查询结果

查询结果为实体对象:

// 接口返回值为实体对象
User getUserByName(String name);
<!-- resultType:属性需要指定返回值的全限定类名或者是别名-->
<select id="getUserByName" resultType="com.jx.app.mybatis.entity.User">
    SELECT *
    FROM user u
    WHERE u.user_name = #{name}
</select>

注意:返回值是一个实体类对象时,返回结果只能是一条数据或者 null,如果查询出来是多条数据就会报错。

查询结果为集合:

// 接口返回值为集合类型,并指定对应泛型
List<User> getUserByName(@Param("name") String name);
<!-- resultType:需要指定集合中泛型对应类的全限定类名或者别名-->
<select id="getUserByName" resultType="com.jx.app.mybatis.entity.User">
    SELECT * FROM user u
</select>

注意:如果查询出来一条或多条结果就会封装到集合中,如果没有结果就会返回空集合但是不会返回 null。

查询结果为 map 集合:

// 接口返回值是map类型
Map<String,Object> getUserToMap();
<!-- 将查询的接口以字段名为key,然后字段值为 value 的 map-->
<select id="getUserToMap" resultType="java.util.Map">
    SELECT * FROM user u
</select>

注意:查询结果为 map 只能查询一条数据,查询出多条就会报错,而且如果某个字段是 null,这个字段不会封装到 map 中。

多条结果封装成 map:

/**
 * 如果查询多条数据也想封装成 map,@MapKey 可以指定查询出来那个字段可以作为 key,
 * 然后这一条数据又会封装成一个 map 作为 value 存储进去
*/
@MapKey("id")
Map<String, Map<String,Object>> getUserToMap();

获取自增主键:在插入数据时,可以获取插入数据后对应的自动递增的 id。

// 插入元素
int insert(User user);
<!-- 
    useGeneratedKeys:设置是否能够获取到自增主键
    keyProperty:获取到的主键的值存储到参数实体的哪个属性
-->
<insert id="insert" useGeneratedKeys="true" keyProperty="id">
    INSERT INTO user values(null,#{userName},#{password},#{money})
</insert>

resultMap 字段关系映射:查询出来的结果与实体类上的字段名称不一致,我们就需要通过 resultMap 属性去自定义映射关系。

方式一:字段起别名,可以在 SQL 语句中把字段名通过起别名方式与属性名一一对应。

方式二:使用 resultMap 映射,将查询出来字段名与对象属性名进行一个自定义映射。

<!-- 设置返回值类型为 resultMap,并且创建一个映射-->
<select id="getUserList" resultMap="UserListMap">
    SELECT * FROM user u
</select>

<!-- 关系映射,id属性:需要和映射返回值相同,type属性:就是映射的实体对象类型-->
<!-- id:数据库主键字段,result:普通字段。
       column属性:查询数据库对应字段名,property属性:需要映射的属性名称。
 -->
<resultMap id="UserListMap" type="com.jx.app.mybatis.entity.User">
    <id column="id" property="id"/>
    <result column="user_name" property="userName"/>
    <result column="password" property="password"/>
    <result column="money" property="money"/>
</resultMap>

注意:如果查询出来字段名与属性名对应不上,不会报错,只是他们对应属性值都是对象默认值。

5、Mybatis 关系映射处理

两个实体:Student 和 Teacher,一个学生有一个老师,一个老师有多个学生。

@Data
public class Student {
    private String id;
    private String studentName;
    private Teacher teacher;
}
@Data
public class Teacher {
    private String id;
    private String teacherName;
    private List<Student> students;
}

5.1、多对一关系映射处理

方式一:使用连接查询查询对学生对应的老师信息,然后使用级联属性映射。

<!-- 使用连接查询获取学生信息以及老师信息-->
<select id="getStudentById" resultMap="StudentMap">
    SELECT * FROM student s
    LEFT JOIN teacher t ON s.t_id = t.id
    WHERE s.id = #{id}
</select>

<!-- 使用级联方式进行属性映射-->
<resultMap id="StudentMap" type="com.jx.app.mybatis.entity.Student">
    <id column="id" property="id"/>
    <result column="student_name" property="studentName"/>
    <result column="t_id" property="teacher.id"/>
    <result column="teacher_name" property="teacher.teacherName"/>
</resultMap>

方式二:使用连接查询查询对学生对应的老师信息,然后通过 resultMap 进行关系映射。

<!-- 使用连接查询获取学生信息以及老师信息-->
<select id="getStudentById" resultMap="StudentMap">
    SELECT * FROM student s
    LEFT JOIN teacher t ON s.t_id = t.id
    WHERE s.id = #{id}
</select>

<!-- 使用 association 关系映射-->
<resultMap id="StudentMap" type="com.jx.app.mybatis.entity.Student">
    <id column="id" property="id"/>
    <result column="student_name" property="studentName"/>
    <!-- property:需要映射的属性名,javaType:这个属性的 java 类型是什么-->
    <association property="teacher" javaType="com.jx.app.mybatis.entity.Teacher">
        <id column="t_id" property="id"/>
        <result column="teacher_name" property="teacherName"/>
    </association>
</resultMap>

方式三:通过子查询去查询老师信息,然后通过 resultMap 进行关系映射。

<!-- 先获取学生信息-->
<select id="getStudentById" resultMap="StudentMap">
    SELECT * from student WHERE id = #{id}
</select>

<resultMap id="StudentMap" type="com.jx.app.mybatis.entity.Student">
    <id property="id" column="id"/>
    <result property="studentName" column="student_name"/>
    <!-- select:子查询的唯一标识(命名空间+id),column:给子查询的查询参数-->
    <association property="teacher" select="com.jx.app.mybatis.mapper.UserMapper.getTeacher" column="t_id"/>
</resultMap>

<!-- 子查询-->
<select id="getTeacher" resultType="com.jx.app.mybatis.entity.Teacher">
    SELECT * from teacher where id = #{t_id}
</select>

注意:子查询有一个好处就是可以设置关联对象的延迟加载,只有在使用到延迟对象时才会去执行对应的子查询 SQL 语句然后返回结果。

  • 需要开启 mybatis 的全局懒加载设置,<setting name="lazyLoadingEnabled" value="true"/>
  • association 有一个 fetchType 属性手动控制懒加载,值有 lazy(懒加载)、eager(立即加载),如果不设置这个属性默认是懒加载。

5.2、一对多关系映射处理

方式一:通过连接查询出老师对应的所有学生信息,然后通过 resultMap 进行关系映射。

<!-- 连接查询-->
<select id="getTeacherById" resultMap="TeacherMap">
    SELECT * FROM teacher t
    LEFT JOIN student s ON t.id = s.t_id
    WHERE t.id = #{id}
</select>

<resultMap id="TeacherMap" type="com.jx.app.mybatis.entity.Teacher">
    <id property="id" column="id"/>
    <result property="teacherName" column="teacher_name"/>
     <!-- 查询出来学生信息进行集合映射,ofType:集合泛型中的属性-->
    <collection property="students" ofType="com.jx.app.mybatis.entity.Student">
        <id property="id" column="s_id"/>
        <result property="studentName" column="student_name"/>
    </collection>
</resultMap>

方式二:分步查询老师信息和学生信息,然后通过 resultMap 映射关联。

<select id="getTeacherById" resultMap="TeacherMap">
    SELECT * FROM teacher t
    WHERE t.id = #{id}
</select>

<resultMap id="TeacherMap" type="com.jx.app.mybatis.entity.Teacher">
    <id property="id" column="id"/>
    <result property="teacherName" column="teacher_name"/>
    <!-- 查询出来学生信息进行集合映射,ofType:集合泛型中的属性-->
    <collection property="students" ofType="com.jx.app.mybatis.entity.Student"
            select="com.jx.app.mybatis.mapper.UserMapper.getStudent"
            column="id">
    </collection>
</resultMap>

<select id="getStudent" resultType="com.jx.app.mybatis.entity.Student">
    select * from student where t_id = #{tid}
</select> 

6、Mybatis 动态 SQL

​ 根根据特定的条件动态拼接 SQL 语句的功能,它就是解决在拼接 SQL 时字符串问题。

if 标签:会根据标签的 test 属性对应表达式返回 true 或者 false 决定是否拼接到 SQL 语句中。

// 使用 if 进行多条件查询
List<User> DynamicSQL(User user);
<select id="DynamicSQL" resultType="com.jx.app.mybatis.entity.User">
    select * from user 
    where 1=1
    <!-- 如果查询条件有 username 就会在 SQL 中进行拼接-->
    <if test="userName != null and userName != ''">
        and user_name = #{userName}
    </if>
    <if test="money != null and money != ''">
        and money = #{money}
    </if>
</select>

where 标签:动态生成 where 条件语句,根据拼接 SQL 在前面添加或去掉 and、or 关键字,如果没有条件就不会有 where 关键字。

<select id="DynamicSQL" resultType="com.jx.app.mybatis.entity.User">
    select * from user
    <!-- 会动态生成 where 关键字,并且去除或添加开头的 and、or 关键字-->
    <where>
        <!-- 如果查询条件有 username 就会在 SQL 中进行拼接-->
        <if test="userName != null and userName != ''">
            and user_name = #{userName}
        </if>
        <if test="money != null and money != ''">
            or money = #{money}
        </if>
    </where>
</select>

trim 标签:如果拼接 SQL 字符串有内容可以在内容前后添加内容,如果没有内容也没有任何效果。

<select id="DynamicSQL" resultType="com.jx.app.mybatis.entity.User">
    select * from user
    <!--
        prefix|suffix:在内容的前面|后面添加指定内容
        prefixOverrides|suffixOverrides:在内容的前面|后面去掉指定内容
    -->
    <trim prefix="where" suffix="" prefixOverrides="and|or" suffixOverrides="">
            <if test="userName != null and userName != ''">
                and user_name = #{userName}
            </if>
            <if test="money != null and money != ''">
                or money = #{money}
            </if>
    </trim>
</select>

chose…when…otherwise 标签:相当于 if…eles if…else,指定条件选择一个进行执行,其它内容不执行。

<select id="DynamicSQL" resultType="com.jx.app.mybatis.entity.User">
    select * from user
    <where>
        <!-- 只选择一个条件进行执行,如果 when 都不满足则执行 otherwise 中的内容-->
        <choose>
            <when test="userName != null and userName != ''">
                user_name = #{userName}
            </when>
            <when test="money != null and money != ''">
                money = #{money}
            </when>
            <otherwise>
                id = #{id}
            </otherwise>
        </choose>
    </where>
</select>

注意:这个条件选择执行只会满足一个,要么是 when 中的一个要么就是 otherwise。

foreach 标签:如果参数是集合类型,可以通过标签遍历集合中内容,例如进行批量删除、增加等操作。

// 批量删除
int deleteBatch(@Param("ids") List<String> ids);
<delete id="deleteBatch">
    delete from user
    <where>
        id in
        <!-- collection:操作的集合参数,item:遍历出来的每个元素,open:指定开始内容,
                 close:指定结束内容,index:遍历到的下标,separator:指定每个元素之间的分隔符
            -->
        <foreach collection="ids" item="id" close=")" open="(" separator="," index="i">
            #{id}
        </foreach>
    </where>
</delete>

sql 标签:对常用的 SQL 语句进行一个抽取,如果在其它地方使用直接引用。

<!-- id:唯一标识 sql 标签,在引用时通过 id 引入-->
<sql id="CommonSQL">
    id,user_name,password,money
</sql>

<!-- 通过 include 标签进行引入动态的 sql-->
<select id="selectAll" resultType="com.jx.app.mybatis.entity.User">
    select <include refid="CommonSQL"/> from user
</select>

7、Mybatis 缓存

一级缓存:这个级别缓存是 SqlSession 级别的缓存,通过同一个 SqlSession 对象去查询数据,那么在第二次查询就会去缓存中获取而不会去查询数据库,这种缓存是默认开启的。

@Test
public void test4(){
    SqlSession sqlSession = MybatisUtils.getSqlSession();

    UserMapper userMapper1 = sqlSession.getMapper(UserMapper.class);
    List<User> allUser1 = userMapper1.findAllUser();
    System.out.println(allUser1);

    // 即使是不同 mapper 对象,但是是同一个 sqlSession,那么第二次就会去缓存中取数据
    UserMapper userMapper2 = sqlSession.getMapper(UserMapper.class);
    List<User> allUser2 = userMapper2.findAllUser();
    System.out.println(allUser2);
}

一级缓存失效:

  • 使用不同的 SqlSession 进行查询数据。
  • 同一个 SqlSession 但是查询条件不同。
  • 同一个 SqlSession 的两次查询之间执行了其它的增、删、改等操作。
  • 同一个 SqlSession 的两次查询之间手动清空了缓存。
// 手动清空缓存
sqlSession.clearCache();

二级缓存:二级缓存是 SqlSessionFactory 级别的缓存,通过同一个 SqlSessionFactory 创建的 SqlSession 去查询结果会被缓存,那么第二次去执行相同查询就会去缓存中查询,二级缓存需要手动开启。

  • 需要在 mybatis 核心配置文件中开启缓存。
<settings>
    <!-- 开启全局缓存,默认是开启的-->
    <setting name="cacheEnabled" value="true"/>
</settings>
  • 在 mapper 映射文件中开启缓存。
<!-- 开启缓存-->
<cache />
@Test
public void test5(){
    SqlSession sqlSession1 = MybatisUtils.getSqlSession();
    SqlSession sqlSession2 = MybatisUtils.getSqlSession();

    UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class);
    List<User> users1 = mapper1.selectAll();
    System.out.println(users1);
    sqlSession1.commit();

    // 同一个 SqlSessionFactory 获取的不同 SqlSession 查询结果会被缓存
    UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class);
    List<User> users2 = mapper2.selectAll();
    System.out.println(users2);
}

注意事项:

  • 必须是同一个 SqlSessionFactory 的 SqlSession 的二级缓存才会生效。
  • 只有每一个将 SqlSession 查询后提交或者关闭,数据才会被缓存。
  • 查询的结果对象必须实现序列化,不然使用缓存会报错。
  • 两次相同查询之间,执行了增、删、改操作,一级缓存、二级缓存都会失效。

image-20230624210726280

二级缓存相关设置:在 mapper 映射文件中的 cache 标签可以设置以下属性。

<!-- 相关设置:
           eviction(缓存回收策略)=LRU(最近最少使用,默认值) | FIFO(先进先出)
           flushInterval:缓存刷新时间,单位秒,不设置就是不刷新就只有执行增删改语句才会刷新
           size:缓存对象数目,防止内存溢出
           readOnly(是否只读)=true(缓存返回是同一个对象,且这个对象不能修改,修改会报错) 
                            false(返回的缓存中的一个拷贝对象,这个对象可以修改,默认值)
-->
<cache eviction="LRU" flushInterval="1000" size="10" readOnly="false"/>

Mybatis 缓存查询顺序:

  • 先查询二级缓存,二级缓存的范围比一级缓存大一些。
  • 如果二级缓存没有命中就回去查询一级缓存。
  • 如果一级缓存也没有命中,就会去查询数据库。
  • SqlSession 关闭后,会将一级缓存的数据写入二级缓存。

第三方缓存工具 EHCache:

  • 导入依赖:
<!-- ehcache和mybatis整合包-->
<dependency>
    <groupId>org.mybatis.caches</groupId>
    <artifactId>mybatis-ehcache</artifactId>
    <version>1.2.1</version>
</dependency>
  • 编写 ehcache 配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<ehcache
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
        updateCheck="false">
    <!--
    diskStore:为缓存路径,ehcache分为内存和磁盘两级,
    此属性定义磁盘的缓存位 置。
    参数解释如下:
    user.home – 用户主目录
    user.dir – 用户当前工作目录
    java.io.tmpdir – 默认临时文件路径
    -->
    <diskStore path="E:\ehcache"/>
    <defaultCache
            eternal="false"
            maxElementsInMemory="10000"
            overflowToDisk="true"
            diskPersistent="false"
            timeToIdleSeconds="1800"
            timeToLiveSeconds="259200"
            memoryStoreEvictionPolicy="LRU"/>
    <cache
            name="cloud_user"
            eternal="false"
            maxElementsInMemory="5000"
            overflowToDisk="false"
            diskPersistent="false"
            timeToIdleSeconds="1800"
            timeToLiveSeconds="1800"
            memoryStoreEvictionPolicy="LRU"/>
    <!--name:缓存名称。
    maxElementsInMemory:缓存最大数目
    maxElementsOnDisk:硬盘最大缓存个数。
    eternal:对象是否永久有效,一但设置了,timeout将不起作用。
    overflowToDisk:是否保存到磁盘,当系统当机时
    timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。 仅当 eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。
    timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建 时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存 活时间无穷大。
    diskPersistent:是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默 认是30MB。每个Cache都应该有自己的一个缓冲区。
    diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。
    memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将 会根据指定的策略去清理内存。
    默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先 出)或是LFU(较少使用)。
    clearOnFlush:内存数量最大时是否清除。 memoryStoreEvictionPolicy:
    可选策略有:
    LRU(最近最少使用,默认策略)、
    FIFO(先进先出)、
    LFU(最少访问次数)。
    FIFO,first in first out,这个是大家最熟的,先进先出。
    LFU, Less Frequently Used,就是上面例子中使用的策略,直白一点就是讲一直以 来最少被使用的。如上面所讲,缓存的元素有一个hit属性,hit值最小的将会被清出缓存。 L'
    RU,Least Recently Used,最近最少使用的,缓存的元素有一个时间戳,当缓存容 量满了,而又需要腾出地方来缓存新的元素的时候,那么现有缓存元素中时间戳离当前时间最远的 元素将被清出缓存。 -->
</ehcache>
  • 使用三方缓存工具:在 mapper 映射文件中修改。
<!-- type:指定缓存类型,不指定就是使用 mybatis 的缓存-->
<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>

8、Mybatis 分页插件

导入依赖:

<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
    <version>5.3.3</version>
</dependency>

设置 mybatis 插件:

<plugins>
    <!-- 设置分页插件拦截器-->
    <plugin interceptor="com.github.pagehelper.PageInterceptor"/>
</plugins>

使用方式:

@Test
public void test6(){
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);

    // 开启分页,在下一个查询语句会进行分页拦截,参数一:页码,参数二:一页数量
    PageHelper.startPage(1,5);

    List<User> users2 = mapper.selectAll();
    
    // 参数是查询后的 list 结果
    PageInfo<User> pageInfo = new PageInfo<>(users2);

    System.out.println(pageInfo.getList());
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值