玄子Share – mybatis-3.5.13 学习笔记

玄子Share - mybatis-3.5.13 学习笔记

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-edDRdx4N-1684580838688)(./assets/68747470733a2f2f6d7962617469732e6f72672f696d616765732f6d7962617469732d6c6f676f2e706e67.png)]

mybatis 官网

官网 https://mybatis.org/mybatis-3/zh/index.html

下载地址

下载地址 https://github.com/mybatis/mybatis-3

Maven 地址

Maven https://mvnrepository.com/artifact/org.mybatis/mybatis

<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.13</version>
</dependency>

XML 构建失败

在 Maven 中指定文件地址

<build>
    <resources>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.xml</include>
                <include>**/*.properties</include>
            </includes>
        </resource>

        <resource>
            <directory>src/main/resources</directory>
            <includes>
                <include>**/*.xml</include>
                <include>**/*.properties</include>
            </includes>
        </resource>
    </resources>
</build>

清理 Maven 构建项目

mvn clean install

mybatis-config.xml

环境(environment)

写死

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url"
                          value="jdbc:mysql://localhost:3306/hospital?TRUE&amp;useUnicode=TRUE&amp;characterEncoding=UTF-8&amp;serverTimezone=GMT%2B8"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="com/xuanzishare/dao/PatientMapper.xml"/>
    </mappers>
</configuration>
  • $ 使用 &amp; 转义

动态插入

mybatis-config.xml

这些属性可以在外部进行配置,并可以进行动态替换。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <properties resource="database.properties"/>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="com/xuanzishare/dao/PatientMapper.xml"/>
    </mappers>
</configuration>
database.properties
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/hospital?useUnicode=TRUE&characterEncoding=UTF-8&serverTimezone=GMT-8
username=root
password=root
重构属性

你既可以在典型的 Java 属性文件中配置这些属性,也可以在 properties 元素的子元素中设置。

<properties resource="org/mybatis/example/config.properties">
  <property name="username" value="root"/>
  <property name="password" value="root"/>
</properties>

类型别名(typeAliases)

类名限定

类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写。

<typeAliases>
    <typeAlias type="com.xuanzishare.entity.Patient" alias="Patient"/>
    <typeAlias type="com.xuanzishare.dao.PatientMapper.xml" alias="PatientMapper"/>
</typeAliases>

包名

也可以指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean

<typeAliases>
    <package name="com.xuanzishare.entity/"/>
</typeAliases>

每一个在包 com.xuanzishare.entity 中的 Java Bean,在没有注解的情况下,会使用 Bean 的首字母小写的非限定类名来作为它的别名。

注解

有注解,别名为其注解值

@Alias("patient")
public class Patient {

    private int patientId;
    private String password;
    private String birthDate;
    private String gender;
}

如果 IDEA 提示无法解析别名,但代码正常运行,可尝试重启IDEA刷新缓存

MybatisUtil.java

在 dao 包内

package com.xuanzishare.dao;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

public class MybatisUtil {
    private static SqlSessionFactory sqlSessionFactory;

    static {
        String resource = "mybatis-config.xml";
        InputStream inputStream = null;
        try {
            inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }

    public static SqlSession getSqlSession() {
        return sqlSessionFactory.openSession();
    }
}

自动提交

public static SqlSession getSqlSession() {
    return sqlSessionFactory.openSession(true);
	}

DaoMapper.xml

使用标签指定

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xuanzishare.dao.PatientMapper">
    <insert id="insertPatientInfo" parameterType="com.xuanzishare.entity.Patient">
        insert into patient (password, birthDate, gender, patientName, phoneNum, email, identityNum, address) values
        (#{password},#{birthDate},#{gender},#{patientName},#{phoneNum},#{email},#{identityNum},#{address});
    </insert>
    <update id="updatePatientInfoByPatientId" parameterType="com.xuanzishare.entity.Patient">
        update patient set password=#{password} where patientID= #{patientId}
    </update>
    <delete id="deletePatientByPatientId" parameterType="int">
        delete from patient where patientID= #{patientId};
    </delete>
    <select id="selectPatient" resultType="com.xuanzishare.entity.Patient" parameterType="int">
        select * from patient where patientID=#{id};
    </select>
</mapper>
  • namespace:dao 层类名
  • id:方法名
  • parameterType:传参类型
  • resultType:返回值类型

标签注入

写 sql 语句不提示,检查 IDEA 是否连接数据库并指定架构,如果还不行就点左边的小灯泡自行配置语言注入为 MySQL

万能 Map

使用 key 自定义字段

Map<String, Object> patientMap = new HashMap<>();
patientMap.put("id", 1);
patientMap.put("pwd", 12341);
patientMapper.updatePatientInfoByPatientId2(patientMap);
<update id="updatePatientInfoByPatientId2" parameterType="map">
    update patient
    set password=#{pwd}
    where patientID = #{id}
</update>

结果集映射

<select id="selectPatientInfo" resultMap="PatientMap">
    select *
    from patient
    where gender = #{gender};
</select>

<resultMap id="PatientMap" type="Patient">
    <id property="patientId" column="patientID"/>
    <result property="password" column="password"/>
    <result property="gender" column="gender"/>
</resultMap>
  • resultMap:结果集
  • resultMap 里的 id 就是 resultMap 的值 可以随便起名字
  • typ:返回值类型
  • property:属性名
  • column:数据库字段名

Main.java

获取对象 执行 sql

package com.xuanzishare;

import com.xuanzishare.dao.MybatisUtil;
import com.xuanzishare.dao.PatientMapper;
import com.xuanzishare.entity.Patient;
import org.apache.ibatis.session.SqlSession;


public class Main {
    public static void main(String[] args) {
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        // 获取 sqlSession 对象
        PatientMapper patientMapper = sqlSession.getMapper(PatientMapper.class);
        // 获取 patientMapper 对象
        
        for (Patient patient : patientMapper.selectPatient(1)) {
            System.out.println(patient);
        }
        
        patientMapper.updatePatientInfoByPatientId(new Patient(4, "123555", "2022-12-01", "1", "1", "1", "1", "1daga", "1"));
       
        sqlSession.commit();
		// 提交事务
        sqlSession.close();
        // 关闭流
    }
}
List<Patient> objects = sqlSession.selectList("com.xuanzishare.dao.PatientMapper.selectPatient");
//获取 patientMapper 对象 方法
for (Patient object : objects) {
    System.out.println(object);
}

日志 log4j 2

Maven 地址

<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core -->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.20.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-api -->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.20.0</version>
</dependency>

mybatis-config.xml

<settings>
    <setting name="logImpl" value="LOG4J2"/>
</settings>
设置名 描述 有效值 默认值
logImpl 指定 MyBatis 所用日志的具体实现,未指定时将自动查找。 SLF4J | LOG4J(3.5.9 起废弃) | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING 未设置

分页

select * from patientlimit startIndex,pageSize;
# 起始下标 页面大小
<select id="selectPatientInfoLimit" resultType="Patient" parameterType="map">
    select *
    from patient
    limit #{startIndex},#{pageSize};
</select>
PatientMapper patientMapper = sqlSession.getMapper(PatientMapper.class);
       Map<String, Object> patientLimitMap = new HashMap<>();
       patientLimitMap.put("startIndex", 0);
       patientLimitMap.put("pageSize", 10);
       List<Patient> patientList = patientMapper.selectPatientInfoLimit(patientLimitMap);
       for (Patient patient : patientList) {
           System.out.println(patient);
       }

注解开发

@Select( )

package com.xuanzishare.dao;


import com.xuanzishare.entity.Checkitem;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;

import java.util.List;

public interface CheckitemMapper {

    @Select("select * from  Checkitem")
    List<Checkitem> selectCheckItemInfo();

    @Select("select * from  Checkitem where checkitemId =#{checkItemID} and checkitemName =#{CheckitemName}")
    List<Checkitem> selectCheckByIdAndCheckitemName(@Param("checkItemID") int id, @Param("CheckitemName") String name);

    @Insert("insert into Checkitem (CheckitemName,checkItemCost) values (#{checkItemName},#{checkItemCost})")
    int insertCheckItem(Checkitem checkitem);
}
  • @Select( ):注解标签
  • @Param( ):参数类型
    • 基本数据类型:一个可以不写,多个写,最好都写
    • 对象引用类型:不用写

只能执行简单的增删改,无法写业务

Lombok

常用

@Data
@AllArgsConstructor
@NoArgsConstructor
  • @Data:基础POJO
  • @AllArgsConstructor:有参构造
  • @NoArgsConstructor:无参构造
@Getter and @Setter
@FieldNameConstants
@ToString
@EqualsAndHashCode
@AllArgsConstructor, @RequiredArgsConstructor and @NoArgsConstructor
@Log, @Log4j, @Log4j2, @Slf4j, @XSlf4j, @CommonsLog, @JBossLog, @Flogger, @CustomLog
@Data
@Builder
@SuperBuilder
@Singular
@Delegate
@Value
@Accessors
@Wither
@With
@SneakyThrows
@StandardException
@val
@var
experimental @var
@UtilityClass
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.26</version>
</dependency>

多对一 与 一对多

package com.xuanzishare.dao;

import com.xuanzishare.entity.Checkitem;
import com.xuanzishare.entity.Department;
import com.xuanzishare.entity.DepartmentCheckitem;

import java.util.List;

public interface DepartmentCheckitemMapper {

    List<DepartmentCheckitem> selectDepartmentCheckitem();

    List<Department> selectDepartment();

    List<Checkitem> selectCheckitem();
    //    多对一 多个检查项目对应一个科室
    
    List<DepartmentCheckitem> selectDepartmentCheckitem2();

    List<Department> selectDepartment2();

    List<Checkitem> selectCheckitem2();
//    一对多 一个科室对应多个检查项目

}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xuanzishare.dao.DepartmentCheckitemMapper">
    <!-- 多对一  多个检查项目对应一个科室 -->
    <select id="selectDepartmentCheckitem" resultMap="dcMap">
        select *
        from department_checkitem
                 inner join department on department_checkitem.depID = department.depID
                 inner join checkitem on department_checkitem.checkItemID = checkitem.checkItemID;
    </select>
    <select id="selectCheckitem" resultType="Checkitem">
        select *
        from Checkitem
        where checkItemID = #{checkItemID};
    </select>
    <select id="selectDepartment" resultType="Department">
        select *
        from department
        where depID = #{depID};
    </select>
    <!--第一种,多对一,按照查询嵌套处理-->
    <!--    <resultMap id="dcMap" type="DepartmentCheckitem">-->
    <!--        <id property="id" column="id"/>-->
    <!--        <association property="checkitem" column="checkItemID" javaType="Checkitem" select="selectCheckitem"/>-->
    <!--        <association property="department" column="depID" javaType="Department" select="selectDepartment"/>-->
    <!--    </resultMap>-->
    <!--第二种,多对一 按照结果嵌套查询-->
    <resultMap id="dcMap" type="DepartmentCheckitem">
        <id property="id" column="id"/>
        <association property="checkitem" javaType="Checkitem">
            <id property="checkItemId" column="checkItemID"/>
            <result property="checkItemName" column="checkItemName"/>
            <result property="checkItemCost" column="checkItemCost"/>
        </association>
        <association property="department" javaType="Department">
            <id property="depId" column="depID"/>
            <result property="depName" column="depName"/>
        </association>
    </resultMap>
    
    
    <!-- ===================================================   -->
    <!-- ===================================================   -->


    <!-- 一对一  一个科室对应多个检查项目 -->
    <select id="selectDepartmentCheckitem2" resultMap="dcMap2">
        SELECT *
        FROM department_checkitem
                 LEFT JOIN department ON department_checkitem.depID = department.depID
                 LEFT JOIN checkitem ON department_checkitem.checkItemID = checkitem.checkItemID;
    </select>
    <select id="selectDepartment2" resultType="Department">
        select *
        from Checkitem
        where checkItemID = #{checkItemID};
    </select>
    <select id="selectCheckitem2" resultType="Checkitem">
        select *
        from department
        where depID = #{depID};
    </select>
    <!-- 第一种,一对多,按照查询嵌套处理-->
    <resultMap id="dcMap2" type="DepartmentCheckitem">
        <id property="id" column="id"/>
        <collection property="checkitem" column="checkItemID" javaType="Checkitem" select="selectCheckitem"/>
        <collection property="department" column="depID" javaType="Department" select="selectDepartment"/>
    </resultMap>
    <!--第二种,一对多 按照结果嵌套查询-->
    <!--    <resultMap id="dcMap2" type="DepartmentCheckitem">-->
    <!--        <id property="id" column="id"/>-->
    <!--        <collection property="checkitem" ofType="Checkitem">-->
    <!--            <id property="checkItemId" column="checkItemID"/>-->
    <!--            <result property="checkItemName" column="checkItemName"/>-->
    <!--            <result property="checkItemCost" column="checkItemCost"/>-->
    <!--        </collection>-->
    <!--        <collection property="department" ofType="Department">-->
    <!--            <id property="depId" column="depID"/>-->
    <!--            <result property="depName" column="depName"/>-->
    <!--        </collection>-->
    <!--    </resultMap>-->
</mapper>

多对一

  • association:关联
    • property:字段名
    • column:数据库名称
    • javaType:返回值类型
    • select:子查询来源

一对多

  • collection:集合
    • property:字段名
    • column:数据库名称
    • ofType:返回值类型(集合泛型)
    • select:子查询来源

动态 Sql

根据不同的条件,执行不同的 sql 类似于 java 的方法重载

if

//    动态 sql Map 限定传参 if 判断
List<Patient> selecPatientInfo(Map<String, Object> patientMap);
//  Main 执行 sql
 	    SqlSession sqlSession = MybatisUtil.getSqlSession();
        PatientMapper patientMapper = sqlSession.getMapper(PatientMapper.class);
        Map<String, Object> patientMap = new HashMap<>();
        patientMap.put("password", "312314");
        patientMap.put("gender", "男");
        patientMap.put("identityNum", "3223123");
        List<Patient> patientList = patientMapper.updatePatientInfo(patientMap);
     	for (Patient patient : patientList) {
          System.out.println(patient);
     	}
<select id="selecPatientInfo" resultType="Patient" parameterType="map">
    select * from patient where 1=1
    <if test="password != null">
        and password=#{password}
    </if>
    <if test="gender != null">
        and gender=#{gender}
    </if>
</select>
  • where 1=1 保证执行 查询
  • test:判断调教成立执行 sql

choose (when, otherwise)

<select id="selecPatientInfo" resultType="Patient" parameterType="map">
    select * from patient
    <where>
        <choose>
            <when test="password != null">
                and password=
                #{password}
            </when>
            <when test="gender != null">
                and  gender=
                #{gender}
            </when>
            <otherwise>
                identityNum=#{identityNum}
            </otherwise>
        </choose>
    </where>
</select>
  • choose:类似于 java 中的 switch 关键字
  • when:类似 java 中的 case 关键字
  • otherwise:类似于 java 中的 default 关键字
  • 如果 when 均不成立 才执行 otherwise
  • when 自带 brea 机制,一个成立就直接结束后面的判断

trim (where, set)

<select id="selecPatientInfo" resultType="Patient" parameterType="map">
    select * from patient
    <where>
        <if test="password != null">
            and password=#{password}
        </if>
        <if test="gender != null">
            and gender=#{gender}
        </if>
    </where>
</select>
  • where:只有在有参数的时候才会执行
  • 若子句的开头为 ANDORwhere会自动去除(保险最好都写上)
//    动态 sql Map 限定传参 set 判断
int updatePatientInfo(Map<String, Object> patientMap);
//  Main 执行 sql
      	SqlSession sqlSession = MybatisUtil.getSqlSession();
        PatientMapper patientMapper = sqlSession.getMapper(PatientMapper.class);
        Map<String, Object> patientMap = new HashMap<>();
        patientMap.put("password", "312314");
        patientMap.put("gender", "男");
        patientMap.put("identityNum", "3223123");
        int patientList = patientMapper.updatePatientInfo(patientMap);
        System.out.println(patientList + ":行受影响");
<update id="updatePatientInfo" parameterType="map">
    update patient
    <set>
        <if test="password != null">
            password=#{password},
        </if>
        <if test="gender != null">
            gender=#{gender},
        </if>
    </set>
    <where>
        identityNum=#{identityNum}
    </where>
</update>
  • set:只有在有参数的时候才会执行
  • 会自动删掉 sql 结尾额外的逗号(保险最好都写上)
<trim prefix="WHERE" prefixOverrides="AND |OR ">
    ...
</trim>

<trim prefix="SET" suffixOverrides=",">
    ...
</trim>
  • trim:定制条件
  • prefix:设置前缀
  • prefixOverrides忽略通过|分隔的内容(AND |OR 中的空格是必要的)
  • 移除所有prefixOverrides属性中指定的内容,并且插入prefix属性中指定的内容

foreach

select * from patient where (patientID=1 and patientID=2 and patientID=3)
-- 这里也可以用  where patientID IN(1,2,3) 只是为了练习拼接 sql
// 动态 sql foreach 便利
List<Patient> selecPatientInfoForeach(Map<String, Object> patientMap);
// Main 执行 sql
     	SqlSession sqlSession = MybatisUtil.getSqlSession();
        PatientMapper patientMapper = sqlSession.getMapper(PatientMapper.class);
        Map<String, Object> patientMap = new HashMap<>();
        ArrayList<Integer> patientIdList = new ArrayList<>();
        patientIdList.add(1);
        patientIdList.add(2);
        patientIdList.add(5);
        patientMap.put("ids", patientIdList);
        List<Patient> patientList = patientMapper.selecPatientInfoForeach(patientMap);
        for (Patient patient : patientList) {
            System.out.println(patient);
        }
<select id="selecPatientInfoForeach" resultType="Patient" parameterType="map">
    select *
    from patient
    <where>
        <foreach item="patientID" collection="ids" open="and (" separator="or" close=")">
            patientID=#{patientID}
        </foreach>
    </where>
</select>
  • foreach:遍历
  • collection:集合名称,对应 map 的 key
  • item:集合的每一项,对应 list 的每一项
  • open:sql 以什么开头
  • close:sql 以什么结尾
  • separator: sql 以什么分隔
  • 里面写拼接的 sql

在写这类复杂的拼接 可以先在数据库中写好 正确的完整 sql 在来替换拆分

sql 片段

在使用 sql 的时候 会有一些重复性的 判断,例如上面的案例,都判断了titlegender类似于这样的 sql 就可以抽离成 sql 片段,以复用

 <update id="updatePatientInfo" parameterType="map">
        update patient
        <set>
            <include refid="if-password-gender"/>
        </set>
        <where>
            identityNum=#{identityNum}
        </where>
</update>

<sql id="if-password-gender">
    <if test="password != null">
        password=#{password},
    </if>
    <if test="gender != null">
        gender=#{gender},
    </if>
</sql>
  • sql:抽离出来的 sql 片段
  • id:片段名称(见名知意)
  • include:在需要使用片段的地方,导入片段
  • refid:sql 片段名称
  • sql 片段不要包含 where 语句
  • 尽量提取简单的 sql 片段以提高,复用性

script

要在带注解的映射器接口类中使用动态 SQL,可以使用script元素。

    @Update({"<script>",
      "update Author",
      "  <set>",
      "    <if test='username != null'>username=#{username},</if>",
      "    <if test='password != null'>password=#{password},</if>",
      "    <if test='email != null'>email=#{email},</if>",
      "    <if test='bio != null'>bio=#{bio}</if>",
      "  </set>",
      "where id=#{id}",
      "</script>"})
    void updateAuthorValues(Author author);

bind

bind 元素允许你在 OGNL 表达式以外创建一个变量,并将其绑定到当前的上下文。

<select id="selectBlogsLike" resultType="Blog">
  <bind name="pattern" value="'%' + _parameter.getTitle() + '%'" />
  SELECT * FROM BLOG
  WHERE title LIKE #{pattern}
</select>

缓存

设置名 描述 有效值 默认值
cacheEnabled 全局性地开启或关闭所有映射器配置文件中已配置的任何缓存。 true | false true

默认情况下,只启用了本地的会话缓存,它仅仅对一个会话中的数据进行缓存。 要启用全局的二级缓存,只需要在你的 SQL 映射文件中添加一行:

<cache/>

基本上就是这样。这个简单语句的效果如下:

  • 映射语句文件中的所有 select 语句的结果将会被缓存。
  • 映射语句文件中的所有 insert、update 和 delete 语句会刷新缓存。
  • 缓存会使用最近最少使用算法(LRU, Least Recently Used)算法来清除不需要的缓存。
  • 缓存不会定时进行刷新(也就是说,没有刷新间隔)。
  • 缓存会保存列表或对象(无论查询方法返回哪种)的 1024 个引用。
  • 缓存会被视为读/写缓存,这意味着获取到的对象并不是共享的,可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。

提示 缓存只作用于 cache 标签所在的映射文件中的语句。如果你混合使用 Java API 和 XML 映射文件,在共用接口中的语句将不会被默认缓存。你需要使用 @CacheNamespaceRef 注解指定缓存作用域。

这些属性可以通过 cache 元素的属性来修改。比如:

<cache
  eviction="FIFO"
  flushInterval="60000"
  size="512"
  readOnly="true"/>

这个更高级的配置创建了一个 FIFO 缓存,每隔 60 秒刷新,最多可以存储结果对象或列表的 512 个引用,而且返回的对象被认为是只读的,因此对它们进行修改可能会在不同线程中的调用者产生冲突。

可用的清除策略有:

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

默认的清除策略是 LRU。

flushInterval(刷新间隔)属性可以被设置为任意的正整数,设置的值应该是一个以毫秒为单位的合理时间量。 默认情况是不设置,也就是没有刷新间隔,缓存仅仅会在调用语句时刷新。

size(引用数目)属性可以被设置为任意正整数,要注意欲缓存对象的大小和运行环境中可用的内存资源。默认值是 1024。

readOnly(只读)属性可以被设置为 true 或 false。只读的缓存会给所有调用者返回缓存对象的相同实例。 因此这些对象不能被修改。这就提供了可观的性能提升。而可读写的缓存会(通过序列化)返回缓存对象的拷贝。 速度上会慢一些,但是更安全,因此默认值是 false。

提示 二级缓存是事务性的。这意味着,当 SqlSession 完成并提交时,或是完成并回滚,但没有执行 flushCache=true 的 insert/delete/update 语句时,缓存会获得更新。

使用自定义缓存

除了上述自定义缓存的方式,你也可以通过实现你自己的缓存,或为其他第三方缓存方案创建适配器,来完全覆盖缓存行为。

Redis

玄子Share - mybatis-3.5.13 学习笔记 5.20

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>