Mybatis(本文章跟的b站狂神说Java进行学习,如果想学习java,可以搜索狂神说)

  • 入门
    • 声明周期和作用域
  • 一、CRUD(增、删、改、查)
    • 1.1 namespace
    • 1.2 selsct
    • 1.3 insert
    • 1.4 update
    • 1.5 delete
    • 1.6 注意点
    • 1.7 万能的Map
    • 1.8 模糊查询
  • 二、配置解析
    • 2.1 核心配置文件
    • 2.2 环境配置(environments)
    • 2.3属性(properties)
    • 2.4 类型别名(typeAliases)
    • 2.5 其他设置(目前不需要太重视)
    • 2.6 映射器(mappers)
  • 三、解决属性名和字段名不一致的问题(侧重点是resultMap的初认识)
    • 3.1 问题
    • 3.2 resultMap
  • 四、日志
    • 4.1 日志工厂
    • 4.2 最简单的配置(STDOUT_LOGGING)
    • 4.3 Log4j
  • 五、分页
    • 5.1 使用Limit分页
    • 5.2 RowBounds分页
  • 六 、使用注解开发
    • 6.1 CRUD
  • 七 、 Lombok
    • 7.1 在IDEA安装Lombok插件
    • 7.2 在项目导入Lombok的jar包
    • 7.3 Lombok的使用
    • 7.4 Lombok常用注解实例
  • 八、数据库关系的多对一、一对多、多对多查询处理
    • 8.1 多对一处理
      • 1. 按照查询嵌套处理
      • 2. 按照结果映射处理
    • 8.2 一对多处理
      • 1. 按照查询嵌套处理
      • 2. 按照结果集嵌套处理
  • 九、动态SQL
    • 9.1 uid为UUID的工具类
    • 9.2 练习动态sql的标签
  • 十、缓存
    • 10.1 简介
    • 10.2 Mybatis缓存
    • 10.3 一级缓存
    • 10.4 二级缓存

入门

声明周期和作用域

代码展示:

package com.jzq.utils;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;
import java.sql.SQLException;public class MybatisUtils {private static SqlSessionFactory sqlSessionFactory;// 从 XML 中构建 SqlSessionFactory// 每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为核心的。static {try {String resource = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);} catch (IOException e) {e.printStackTrace();}}// 既然 有了 SqlSesstionFactory, 顾名思义,我们就可以从中获得SqlSession的实例了// SqlSession 完全包含了面向数据库执行SQL命令所需的所有方法。public static SqlSession getSqlSession() {SqlSession sqlSession = sqlSessionFactory.openSession();return sqlSession;}
}

⭐SqlSessionFactoryBuilder:

  • 一旦创建了SqlSessionFactory,就不需要这个了。
  • 局部变量。
  • 可以通过获取配置文件流来创建SqlSessionFactoryBuilder。

⭐SqlSessionFactory:

  • 可以想象成数据库连接池。
  • SqlSessionFactory一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃或重新创建另一个实例。
  • 单例模式或者静态单例模式。
  • 最佳作用域为应用作用域(程序开始就有,程序结束就关闭)。

⭐⭐代码展示:

@Testpublic void test4() {// 获取一个sqlSessionSqlSession sqlSession = MybatisUtils.getSqlSession();try {UserMapper userMapper = sqlSession.getMapper(UserMapper.class);int i = userMapper.updateUser(new User("wxq", "da", "dsa", "sdas", "dsadsad"));if(i>0) {// 提交事务sqlSession.commit();}} catch (Exception e) {e.printStackTrace();} finally {sqlSession.close();}}

⭐SqlSession:

  • 连接到连接池(SqlSessionFactory)的一个请求!
  • SqlSession的实例不是线程安全的,因此是不能被共享的,所以它的最佳作用域是请求或者方法的作用域。
  • 不能放到类的静态域,或者全局类成员属性
  • 用完后迅速关闭,为了确保每次都可以顺利关闭,可以放到finally中

⭐Mapper

  • 通过SqlSession获取到接口mapper,去完成业务需求(sql)

一、CRUD(增、删、改、查)

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace=绑定了一个对应的Dao/Mapper接口-->
<mapper namespace="com.jzq.dao.user.UserMapper"><!--  id对应的namespace内的某个方法  --><!--  resultType对应了返回结果类型  --><select id="getUserList" resultType="com.jzq.pojo.User">select * from mybatis.user</select><select id="getUserId" resultType="com.jzq.pojo.User" parameterType="String">select * from mybatis.user where user_id = #{user_id}</select>
</mapper>

1.1 namespace

namespace中的包名要和Dao/Mapper的接口的包名一致!

1.2 selsct

<select id="getUserId" resultType="com.jzq.pojo.User" parameterType="String">select * from mybatis.user where user_id = #{user_id}</select>

1.3 insert

<insert id="addUser" parameterType="com.jzq.pojo.User">-- insert into  mybatis.user (user_id, username, password, phone, head_img) values ('${user_id}', '${username}', '${password}', '${phone}', '${head_img}');insert into  mybatis.user (user_id, username, password, phone, head_img) values (#{user_id}, #{username}, #{password}, #{phone}, #{head_img});</insert>

1.4 update

<update id="updateUser" parameterType="com.jzq.pojo.User">update mybatis.user set username=#{username},password=#{password} where user_id=#{user_id}</update>

1.5 delete

<delete id="delUser" parameterType="String">delete from mybatis.user where user_id = #{user_id}</delete>

1.6 注意点

选择、查询等语句的标签参数

  • id:就是对应的namespace接口中的方法名
  • resultType:Sql语句执行的返回值类型
  • parameterType:参数类型

⭐ 注意select或者insert等标签传值的时候通过 ${属性值} 方式传入
⭐Mybatis出现:Unknown column ‘xxx’ in ‘field list’

插入或者修改的数据假如是String时,有如下两种方式
‘${属性值}’ 即在外面包一层引号
#{属性值}, 进行参数化表示

⭐对于增删改,要提交事务

sqlSession.commit();

⭐ 核心配置文件的 mappers配置 resource必须是路径(/分割)

<!--  每个mapper.xml都需要在Mybatis核心配置文件中注册!--><mappers><mapper resource="com/jzq/dao/user/UserMapper.xml"/></mappers>

1.7 万能的Map

假设我们的实体类,或者数据库中的表,字段或者参数过多,我们应当考虑使用Map!

<!--通过map实现参数传递--><insert id="addUserMap" parameterType="Map">insert into mybatis.user(user_id, username, password) values (#{user_id}, #{username}, #{password});</insert>
@Testpublic void test6() {SqlSession sqlSession = MybatisUtils.getSqlSession();try {UserMapper userMapper = sqlSession.getMapper(UserMapper.class);// 传参放到mapMap<String, Object> map = new HashMap<String, Object>();map.put("user_id", "dsxdsczdsxcdada");map.put("username", "dwda");map.put("password", "dsada");int i = userMapper.addUserMap(map);if (i>0) {sqlSession.commit();}} catch (Exception e) {e.printStackTrace();} finally {sqlSession.close();}}

1.8 模糊查询

<select id="getUsers" parameterType="String" resultType="com.jzq.pojo.User">select * from mybatis.user where username like "%"#{username}"%"
</select>

二、配置解析

2.1 核心配置文件

  • 一般以mybatis-config.xml命名
  • Mybatis的配置文件包含了会深深影响Mybatis行为的设置和属性信息。
  • configuration(配置)如下:
properties(属性)
settings(设置)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境配置)
environment(环境变量)
transactionManager(事务管理器)
dataSource(数据源)
databaseIdProvider(数据库厂商标识)
mappers(映射器)

2.2 环境配置(environments)

MyBatis 可以配置成适应多种环境。
记住: 尽管可以配置多个环境,但是每个SqlSessionFactory实例只能选择一种环境
学会使用配置多套运行环境!
Mybatis默认的事务管理器就是 JDBC、连接池:POOLED;

2.3属性(properties)

我们可以通过properties属性来实现引用配置文件。
这些属性都是可外部配置且可动态替换的,既可以在典型的Java属性文件中配置,也可以通过properties元素的子元素来传递。【db.properties】

⭐编写一个配置文件
db.properties

driver=om.mysql.cj.jdbc.Driver
url=jdbc:mysql://x.x.x.x:3306/mybatis?userSSL=true&amp;useUnicode=true&amp;charaterEncoding=UTF-8"
username=xxxxxxx
password=xxxxxxxx

⭐在核心配置文件中引入properties

<!--  引入静态文件  --><properties resource="db.properties"><property name="username" value="xxxx"/><property name="password" value="xxxxxx"/></properties>
  • 可以直接引用外部文件
  • 可以在其中增加一些属性配置
  • 如果两个文件有同一个字段,优先使用外部配置文件的。

2.4 类型别名(typeAliases)

  • 类别别名是为了Java类设置一个短的名字
  • 存在的意义仅在用于减少类完全限定名的冗余

⭐第一种方式:指定一个指定的类

可以给实体类起别名
指定一个固定类,为其起别名

<typeAliases><typeAlias type="com.jzq.pojo.User" alias="User"></typeAlias>
</typeAliases>

⭐第二种方式:指定一个包

<typeAliases><package name="com.jzq.pojo"/>
</typeAliases>
  1. 指定一个包名, Mybatis会在包名下面搜索Java Bean, 其包下的类默认都是小写字母开头类名
  2. 假如给实体类写注解@Alias(“uuuu”), 则是按注解设置的名字为准。

2.5 其他设置(目前不需要太重视)

  • typeHandlers(类型处理器)
  • objectFactory(对象工厂)
  • plugins(插件)
    • mybatis-generators-core
    • mybatis-plus
    • 通用的mapper

2.6 映射器(mappers)

MapperRegistry:注册绑定我们的mapper文件;

方式一: 使用资源路径方式绑定注册

<mappers><mapper resource="com/jzq/dao/user/UserMapper.xml"/>
</mappers>

方式二:使用class文件绑定注册

⭐ 接口和他的Mapper配置文件必须同名
⭐ 接口和他的Maper配置文件必须在同一个包下!

<mappers><mapper class="com.jzq.dao.user.UserMapper"></mapper>
</mappers>

方式三:通过扫描包进行注入绑定

注意点和方式二注意点一样

<mappers><package name="com.jzq.dao"/>
</mappers>

三、解决属性名和字段名不一致的问题(侧重点是resultMap的初认识)

3.1 问题

假如数据库的某张表与实体类的成员属性名不一致,我们在查询时,会遇到一些问题。

⭐ 当然我们可以在sql中通过 as 关键字解决这一个问题:

假如实体类中是 password
数据库的表中是 pwd
我们可以通过:select pwd as password from mybatis.user 来解决这个问题,但是这样终究是太蠢了!!!于是我们还是去了解resultMap来解决这类问题,并深究resultMap的强大!!!

3.2 resultMap

⭐ 解决字段名与实体类属性名不一致的问题

<!--  结果集映射  --><resultMap id="UserMap" type="User"><!--  column数据库中的字段, property实体类中的属性  --><result column="password" property="pwd"></result></resultMap><select id="getUserId" resultMap="UserMap">select * from mybatis.user where user_id = #{user_id}</select>
  • resultMap 元素是MyBatis 中 最重要最强大的元素
  • ResultMap的设计思想是, 对于简单的语句根本不需要配置显式的结果映射, 而对于复杂一点的语句只需要描述它们的关系就行了。
  • ResultMap 最优秀的地方在于,虽然你已经对它相当了解了,但是根本就不需要显示用到他们。

四、日志

4.1 日志工厂

如果一个数据库操作,出现了异常,我们需要排错。日志就是最好的助手!

4.2 最简单的配置(STDOUT_LOGGING)

<settings><setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>

4.3 Log4j

⭐什么是Log4j?

  • Log4j是Apache的一个开源项目,通过使用Log4j,我们可以控制日志信息输送的目的地是 控制台、文件、GUI组件等。
  • 我们可以控制每一条日志的输出格式。
  • 通过定义每一条日志信息的级别,我们能够更加细致地控制日志地生成过程。
  • 通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。

⭐具体步骤:

  1. 导入log4j的包
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version>
</dependency>
  1. 创建log4j.properties (配置文件)
log4j.rootLogger=DEBUG,console,file#控制台输出的相关设置
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%c]-%m%n#文件输出的相关设置
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/jzq.log
log4j.appender.file.MaxFileSize=10mb
log4j.appender.file.Threshold=DEBUG
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n#日志输出级别
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
  1. 配置核心配置文件的日志类型为Log4j
<settings><setting name="logImpl" value="LOG4j"/>
</settings>

⭐简单使用

  1. 要使用Log4j的类中,导入包 import org.apache.log4j.Logger;
  2. 日志对象,参数为当前类的class
    static Logger logger = Logger.getLogger(UserDaoTest.class);
  1. 日志级别
@Testpublic void testLog() {logger.info("info:进入了w");logger.info("debug:进入了x");logger.error("error:进入了q");}

五、分页

5.1 使用Limit分页

  1. 接口
List<User> UserLimit(Map<String, Object> map);
  1. Mapper.xml
<select id="UserLimit" parameterType="Map" resultMap="UserMap">select * from mybatis.user limit #{page}, #{size}</select>
  1. 测试类
@Testpublic void test08() {SqlSession sqlSession = MybatisUtils.getSqlSession();try{UserMapper userMapper = sqlSession.getMapper(UserMapper.class);Map<String, Object> map = new HashMap<>();map.put("page", 0);map.put("size", 5);List<User> userList = userMapper.UserLimit(map);for (User user:userList) {System.out.println(user);}} catch (Exception e) {e.printStackTrace();} finally {sqlSession.close();}}

5.2 RowBounds分页

不在使用sql的Limit分页,通过Java分页

  1. mapper.xml
<select id="UserRowBounds" resultMap="UserMap">select * from mybatis.user
</select>
  1. 测试

通过 new RowBounds(0, 7); 控制数据条数
通过 sqlSession.selectList(“com.jzq.dao.user.UserMapper.UserRowBounds”, null, rowBounds); 进行查询

@Testpublic void UserRowBounds() {SqlSession sqlSession = MybatisUtils.getSqlSession();RowBounds rowBounds = new RowBounds(0, 7);// 通过Java代码层面实现分页List<User> userList = sqlSession.selectList("com.jzq.dao.user.UserMapper.UserRowBounds", null, rowBounds);for (User user:userList) {System.out.println(user);}}

六 、使用注解开发

6.1 CRUD

  1. 工具类返回SqlSession时,加一个Boolean的参数控制事务是否自动提交。

如果commitFlag 为 true则自动提交事务!

public static SqlSession getSqlSession(Boolean commitFlag) {// 传参为 true 表示, 自动提交事务SqlSession sqlSession = sqlSessionFactory.openSession(commitFlag);return sqlSession;}
  1. 编写的接口要增加SQL注解,这样的话就不用写接口对应的xml了
package com.jzq.dao.user;
import *;
public interface UserMapper {// 方法存在多个参数// 引用类型不用加@Param@Select("select * from mybatis.user where username = #{username} && password=#{pwd}")List<User> Login01(Map<String, Object> map);// 测试通过User实体类更新sql// 引用类型不用加@Param@Insert("insert into user(user_id, username, password, phone) values (#{user_id}, #{username}, #{password}, #{phone})")int insertUser01(User user);// 基本类型的参数和String类型,需要加@param// 通过@param 注解完成传参// 多个参数要加@Update("update user set username=#{username}, password=#{pwd} where user_id = #{uid}")int updateUser01(@Param("username") String username, @Param("pwd") String pwd, @Param("uid") String user_id);// 一个参数时可以省略@Delete("delete from user where user_id = #{user_id}")int deleteUser01(String user_id);
}

⭐ 接口必须绑定到核心配置文件中

   <!--  每个mapper.xml都需要在Mybatis核心配置文件中注册!--><mappers><mapper resource="com/jzq/dao/user/UserMapper.xml"/>
<!--        <mapper class="com.jzq.dao.user.UserMapper"></mapper>-->
<!--        <package name="com.jzq.dao"/>--></mappers>

七 、 Lombok

7.1 在IDEA安装Lombok插件

file > settings > Plugins

7.2 在项目导入Lombok的jar包

<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.12</version><scope>provided</scope>
</dependency>

7.3 Lombok的使用

@ToString:作用于类,覆盖默认的toString()方法,可以通过of属性限定显示某些字段,通过exclude属性排除某些字段。


@EqualsAndHashCode:作用于类,覆盖默认的equals和hashCode


@NonNull:主要作用于成员变量和参数中,标识不能为空,否则抛出空指针异常。


@NoArgsConstructor, @RequiredArgsConstructor, @AllArgsConstructor:作用于类上,用于生成构造函数。有staticName、access等属性。staticName属性一旦设定,将采用静态方法的方式生成实例,access属性可以限定访问权限。


@NoArgsConstructor:生成无参构造器;


@RequiredArgsConstructor:生成包含final和@NonNull注解的成员变量的构造器;


@AllArgsConstructor:生成全参构造器;


@Data:作用于类上,是以下注解的集合:@ToString @EqualsAndHashCode @Getter @Setter @RequiredArgsConstructor


@Builder:作用于类上,将类转变为建造者模式


@Log:作用于类上,生成日志变量。针对不同的日志实现产品,有不同的注解:


⭐其他重要注解


@Cleanup:自动关闭资源,针对实现了java.io.Closeable接口的对象有效,如:典型的IO流对象


@SneakyThrows:可以对受检异常进行捕捉并抛出,可以改写上述的main方法如下:


@Synchronized:作用于方法级别,可以替换synchronize关键字或lock锁,用处不大.


7.4 Lombok常用注解实例

package com.jzq.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.ibatis.type.Alias;@Alias("uuuu")@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {private String user_id;private String username;private String pwd;private String phone;private String head_img;
}

八、数据库关系的多对一、一对多、多对多查询处理

⭐ 需要用到 resultMap标签

⭐ association :处理嵌套的对象

  • property:实体类的属性名
  • column:数据库表的字段名
  • javaType:嵌套的实体类型
  • select:查询嵌套实体类的接口名

⭐ collection :处理嵌套的集合

  • ofType:是collection(集合)的泛型类型

8.1 多对一处理

1. 按照查询嵌套处理

这种方式,实际上是通过两个sql语句进行查询
先查询出所有的学生
再通过每个学生的tid查询到对应的老师

<select id="getStudentList" resultMap="StudentTecher">select * from student</select><resultMap id="StudentTecher" type="Student"><result property="uid" column="uid"></result><result property="name" column="name"></result><!--复杂的属性,我们需要单独处理。 对象:association  集合:collection--><association property="tid" column="tid" javaType="Techer" select="getTecherList"></association></resultMap><select id="getTecherList" resultType="Techer">select * from techer where tid = #{tid}</select>

⭐ 运行显示

2. 按照结果映射处理

这种方式通过一个sql进行⭐链表查询
然后通过association属性 序列化对象属性的值

<select id="getStudentList2" resultMap="StudentTecher">select * from student,techerwhere student.tid = techer.tid</select><resultMap id="StudentTecher2" type="Student"><result property="uid" column="uid"></result><result property="name" column="name"></result><association property="tid" column="tid" javaType="Techer"><result property="tid" column="tid"></result><result property="name" column="name"></result><result property="salary" column="salary"></result></association></resultMap>

⭐运行显示

8.2 一对多处理

1. 按照查询嵌套处理

注意⭐collection :

  • property:绑定的实体类的属性
  • column:指的数据库表
  • javaType:就是绑定实体类属性的类型
  • ofType:指的集合泛型的类型
<!--  通过子查询去做   --><select id="getTecher2" resultMap="TecherStudents2">select * from mybatis.techer where tid = #{tid}</select><resultMap id="TecherStudents2" type="Techer"><collection property="studentList" column="tid" javaType="ArrayList" ofType="Student" select="getStudent"></collection></resultMap><select id="getStudent" resultType="Student">select * from student where tid = #{tid}</select>

2. 按照结果集嵌套处理

重点是collection来存放学生类student的对象集合

<resultMap id="TecherStudents" type="Techer"><result property="tid" column="ttid"></result><result property="name" column="tname"></result><result property="salary" column="salary"></result><!--通过collection,处理集合泛型--><!--studentList : 是实体类的属性名字--><!--ofType:是collection的泛型类型--><collection property="studentList" ofType="Student"><result property="uid" column="uid"></result><result property="name" column="sname"></result><result property="tid" column="stid"></result></collection></resultMap>

九、动态SQL

9.1 uid为UUID的工具类

import java.util.UUID;
public class IdUtil {public static String getUUID() {String uid = UUID.randomUUID().toString().replaceAll("-", "");return uid;}
}

9.2 练习动态sql的标签

⭐介绍各大标签

where:
只会在子元素返回内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除。


if: 假如某个字段存在搜索,则添加进sql。 这个可用于动态 0或者n条件搜索


choose: 类似于 switch。 这种情况适用于0或1条件搜索 when: 类似于 case otherwise: 类似于 default


set: 会动态地在行首插入 SET 关键字,并会删掉额外的逗号(这些逗号是在使用条件语句给列赋值时引入的)。


trim: 可以适配WHERE或SET


sql: 可以解决sql多次复用

  1. where 和 if 配合例子
<!--  练习IF WHERE  --><select id="queryBlogIF" parameterType="Map" resultType="Blog">select * from blog<where><if test="name != null">name = #{name}</if><if test="title != null">and title = #{title}</if><if test="first_score != null">and first_score = #{first_score}</if></where></select>
  1. where 和 choose配合例子
<!--  练习choose、when、otherwise  --><select id="queryBlogChoose" parameterType="Map" resultType="Blog">select * from blog<where><choose><when test="name != null">name = #{name}</when><when test="title != null">and title = #{title}</when><otherwise>and first_score = #{first_score}</otherwise></choose></where></select>
  1. set例子
<!--  练习set  --><insert id="updateBlog" parameterType="Blog">update Blog<set><if test="title != null">title = #{title},</if><if test="name != null">name = #{name},</if></set><where>bid = #{bid}</where></insert>
  1. trim完成WHERE例子
<!--  练习trim  --><select id="queryBlogTrim" parameterType="Map" resultType="Blog">select * from blog<trim prefix="WHERE" prefixOverrides="or|and"><if test="name != null">name = #{name}</if><if test="title != null">and title = #{title}</if><if test="first_score != null">and first_score = #{first_score}</if></trim></select>
  1. 练习sql 标签
<sql id="ifififif"><if test="name != null">name = #{name}</if><if test="title != null">and title = #{title}</if><if test="first_score != null">and first_score = #{first_score}</if></sql><select id="queryBlogSql" parameterType="Map" resultType="Blog">select * from mybatis.blog<where><include refid="ifififif"></include></where></select>

十、缓存

10.1 简介

  1. 什么是一级缓存[Cache]?
  • 存在内存的临时数据
  • 将用户经常查询的数据放在缓存(内存)中,用户查询数据库数据时,从缓存中查询,从而提高查询效率,解决了高并发系统的性能问题。
  1. 为什么使用缓存?
  • 减少和数据库交互次数,减少系统开销,提高系统效率。
  1. 什么样的数据能使用缓存?
  • 经常查询并且经常改变的数据

10.2 Mybatis缓存

  • MyBatis包含一个非常强大的查询缓存特性,它可以非常方便的定制和配置缓存。缓存可以极大的提升查询效率。
  • Mybatis系统中默认定义了两级缓存:一级缓存二级缓存
    • 默认情况下,只有一级缓存开启。(SqlSession级别的缓存,也称为本地缓存)
    • 二级缓存需要手动开启和配置,他是基于namespace级别的缓存。
    • 为了提高扩展性,MyBatis定义了缓存接口Cache。我们可以通过实现Cache接口来自定义二级缓存

10.3 一级缓存

  • 一级缓存也叫本地缓存:

    • 与数据库同一次会话期间查询到数据会放在本地缓存中。
    • 以后如果需要获取相同的数据,直接从缓存中拿,没必须再去查数据库。

10.4 二级缓存

  • 二级缓存也叫全局缓存,一级缓存作用域太低了,所以诞生了二级缓存。
  • 基于namespace级别的缓存,一个名称空间,对应一个二级缓存。
  • 工作机制
    • 一个会话查询一条数据,这个数据就会被放在当前会话的一级缓存中;
    • 如果当前会话关闭了,这个会话对应的一级缓存就没了,但是我们想要的是,会话关闭了,一级缓存中的数据被保存到二级缓存中;
    • 新的会话查询信息,就可以在二级缓存中获取内容;
    • 不同的mapper查出的数据会放在自己对应的缓存(map)中;

⭐使用步骤:
1. 开启全局缓存

在mybatis-config.xml中settings中配置

 <settings><!--  开启二级缓存  --><setting name="cacheEnabled" value="true"/></settings>
  1. 在对应的Mapper.xml中配置 标签

带参数的<cache/ >标签
假如有的查询语句不需要缓存,可以将useCache设置为false

<!--配置二级缓存--><cache eviction="FIFO"flushInterval="60000"size="512"readOnly="true"/><select id="queryBlog" parameterType="string" resultType="Blog" useCache="true">select * from mybatis.blog<where>bid = #{bid}</where></select>

当然也可以不设置参数:
但是这种情况运行,实体类要实现序列化接口,否则会报错。

public class Blog implements Serializable

⭐小结

  • 只要开启了二级缓存,在同一个Mapper下就有效;
  • 所有的数据都会先放在一级缓存中;
  • 只有当会话提交,或者关闭的时候,才会提交到二级缓存中!

Mybatis学习之路——看这一篇文章,深刻学会Mybatis相关推荐

  1. 深度学习图像融合_深度学习图像分割必看的12篇文章

    图像分割 Author:孙叔桥 From:有三AI 1 FCN Fully Convolutional Network(FCN)是神经网络用于图像分割任务的鼻祖,后续提出的大部分基于编解码结构的图像分 ...

  2. 【React】看完这篇文章能够学会React初级技术

    本文是根据链接这个视频系列的笔记做的学习记录整理,讲课风格很有趣(2倍速跟小甲鱼声音很像嘿嘿嘿) 在深入学习react之前建议先看看一些react的思想,相关文章我已经总结出来啦!半小时理解react ...

  3. 看完这篇文章轻松学会如何视频剪辑制作

    最近几年,由于大众居家的时间越来越长,短视频这一视频表现形式逐步占据"主流",越来越多的人也开始接触并制作短视频.此前,我有一个朋友也想进入短视频这一行业,所以他就来问我要怎么做. ...

  4. 从入门到精通,看了这篇文章,你离老黑的路就不远了

    关于被入侵 简单说明: 经常有帖子说:"我中xx木马啦,怎么办?"."我的windows有问题,是不是被入侵啦?"等等.通用的做法是查看可疑进程(win98需要 ...

  5. MyBatis学习笔记(1)—使用篇

    MyBatis学习笔记(1)-使用篇 MyBatis学习笔记(2)-映射关系篇 MyBatis学习笔记(3)-高级映射之一对一映射 Mybatis学习笔记(4)-高级映射之一对多映射 Mybatis学 ...

  6. mybatis学习之路----模糊查询实现

    点滴记载,点滴进步,愿自己更上一层楼. 废话不多说,进入主题. 项目还是在上篇  mybatis学习之路----非代理方式的增删改查用法 基础之上进行开发 一个简单的模糊查询sql. SELECT * ...

  7. 学习Nginx,看完这篇超详细的文章就够了

    目录 本文简介 一.Nginx的基本概念 1.1.Nginx是什么? 1.2.Nginx能帮助我们做些什么? 1.3.Nginx的特性 二.Nginx的安装 2.1.环境介绍 2.2.安装Nginx ...

  8. 如果看了这篇文章你还不懂傅里叶变换,那就过来掐死我吧(下)

    上一篇文章发出来之后,为了掐死我,大家真是很下工夫啊,有拿给姐姐看的,有拿给妹妹看的,还有拿给女朋友看的,就是为了听到一句"完全看不懂啊".幸亏我留了个心眼,不然就真的像标题配图那 ...

  9. 运维学python用不上_作为运维你还在想要不要学Python,看完这篇文章再说!

    原标题:作为运维你还在想要不要学Python,看完这篇文章再说! 本文由马哥教育Python自动化实战班5期学员推荐,转载自简书,作者为Li.Yingjie,内容略经小编改编和加工,观点跟作者无关,最 ...

  10. python装饰器原理-看完这篇文章还不懂Python装饰器?

    原标题:看完这篇文章还不懂Python装饰器? 1.必备 2.需求来了 初创公司有N个业务部门,1个基础平台部门,基础平台负责提供底层的功能,如:数据库操作.redis调用.监控API等功能.业务部门 ...

最新文章

  1. 记录一下提取文件夹中所有文件名字
  2. IBMX3650M3服务器8硬盘升级16硬盘的配置方法
  3. Octave添加搜索路径
  4. Java中Boolean是什么?
  5. 任务31:课时介绍 任务32:Cookie-based认证介绍 任务33:34课 :AccountController复制过来没有移除[Authorize]标签...
  6. java实现可选形参_Java:可选的可选实现
  7. 怎么运行java虚拟机_Java代码如何运行在Java虚拟机中
  8. 作者:刘新海(1976-),男,中国人民银行征信中心副研究员
  9. 用C# itextsharp.dll制作PDF文件全攻略
  10. delphi if多个条件_【会计职场】老会计带你玩转Excel,IF函数的使用方法大全!小白必看!...
  11. 又丢脸了,“要源码上门自取”,结果美女真上门了!国内企业再惹争议
  12. WCF技术内幕之面向服务
  13. pip下载安装了第三方模块,Pycharm里面无法导入
  14. 一个整数“犯二的程度”
  15. 基于HC32L13X系列的YModem升级方案
  16. linux安装软件时/usr/lib/python2.7/site-packages/urlgrabber/grabber.py文件异常
  17. Linux——Ubuntu忘记用户密码的解决及登录root
  18. NFC学习笔记(2)——NFC基础知识
  19. 收银管理系统怎么选?哪个牌子好用?这篇干货一次性说明白!
  20. 面试题之如何实现一个深拷贝

热门文章

  1. 计算机音乐《讲真的》,他凭借一首《讲真的》红遍大江南北,希望他不忘初心纯粹做音乐...
  2. 小熊在线一键重装系统教程
  3. 2022阿里笔试分享(2022.3.25)
  4. weblogic错误页面
  5. python调用QQ音乐API
  6. 华三H3C交换机如何配置和使用telnet远程登录设备
  7. deeping linux安装安卓,Deepin 安装Android-studio
  8. 单片机入门必备知识,c语言基础来了
  9. 电脑主板上的一些电子元件
  10. Linux下安装Java运行环境