Mybatis框架

虽然很早之前就已经学习过mybatis框架了,但是由于之前面试的时候被问到mybatis的一些相关的问题答不上来(mybatis的一级缓存和二级缓存),所以花了几天的时间进行复习和整理,写下了这篇博客,篇幅比较长,但基本涵盖了mybatis的重要知识点,希望能对大家有所帮助!

1.什么是Mybatis

MyBatis 是一款优秀的持久层框架,也是一个半自动化的ORM框架 (Object Relationship Mapping) -->对象关系映射;避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集的过程,Mybatis就是帮助程序猿将数据存入数据库中 , 以及从数据库中取数据,虽然原生的jdbc也能完成这个操作,通过框架可以减少重复代码,提高开发效率 ;MyBatis 不仅简单易学、灵活,而且sql语句和java代码的分离,解除sql语句和java代码的耦合,提高了可维护性。

2. 创建一个Mybatis工程的完整步骤

项目结构图
在这里插入图片描述

  1. 创建一个标准的maven项目,并将src目录删除掉,使之成为父模块,然后在父模块下建子模块,这样的好处是:父模块中的依赖都能作用到子模块,这样就不用在每个子模块再导入依赖了。

导入相关依赖

<!--导入依赖-->
    <dependencies>
        <!--导入mysql驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>
        <!--mybatis-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.2</version>
        </dependency>
        <!--junit-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>

如果使用了lombok插件,还需再导入lombok依赖

 <!--lombok插件-->
 <dependency>
 	<groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.12</version>
    <scope>provided</scope>
 </dependency>
  1. 编写全局配置文件mybatis-config.xml
<?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">
<configuration>

    <!--注意配置的顺序,否则会出错:properties-settings-typeAliases -->
    <properties resource="db.properties"/>

    <settings>
        <!--开启日志-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
        <!--开启驼峰命名转换-->
        <setting name="mapUnderscoreToCamelCase" value="true"></setting>
    </settings>

    <!--开启别名的配置-->
    <typeAliases>
        <package name="com.kuang.pojo"></package>
    </typeAliases>

    <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>

    <!--标明每一个mapper.xml的路径-->
    <mappers>
        <!--<mapper resource="com/kuang/dao/UserMapper.xml"/>-->
        <!--使用注解开发,那么mapper中映射绑定的就是接口类-->
        <!--<mapper class="com.kuang.dao.UserMapper"/>-->
        <package name="com.kuang.dao"/>
    </mappers>
</configuration>
  1. 编写数据源相关的配置文件db.properties
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;useUnicode=true&amp;characterEncoding=utf8
username=root
password=123456
  1. 编写生产sqlsession的工具类(注意自动提交事务的设置)
package com.kuang.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;

//编写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 getSession() {
        //return sqlSessionFactory.openSession();//默认是需要手动提交事务
        return  sqlSessionFactory.openSession(true);//设置为true之后就可以自动提交事务了
    }
}
  1. 编写实体类和对应的mapper接口(代码省略)
  2. 编写接口对应的xml配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.kuang.dao.UserMapper">
    <select id="findUserById" resultType="user">
        select * from mybatis.user where id=#{id};
    </select>
</mapper>

补充:xml配置文件的头部可以直接使用全局配置文件的头部进行适当的修改;即将下面圈出的部分改成mapper即可!
在这里插入图片描述
7. 编写测试类

	@Test
    public void test(){

        SqlSession session = MybatisUtils.getSession();
        UserMapper userMapper = session.getMapper(UserMapper.class);
        List<User> users = userMapper.selectUser();
        for (User user:users) {
            System.out.println(user);
        }
        session.close();
    }

可能出现的问题:一般我们在resources目录下编写配置文件(.properties/.xml),启动项目时都会被加载到;但是如果配置文件是在java目录下编写而不是在resources目录下,那么配置文件是不会被加载到的,必须在build中配置resource,解决java目录下的资源导出失败的问题。

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

3.细节

  • 在mapper接口对应的xml文件中编写sql语句需要注意:如果我们传入的参数是一个实体类,那么在sql语句中给字段赋值的参数名就必须要和实体类的属性一致,否则就会出现异常

例如:下面的例子中,User实体类中的属性有name和pwd,所以sql语句中的values值必须也为name和pwd,如果#{name}改成#{sname},那么就会报异常

<insert id="insertUser" parameterType="com.kuang.pojo.User">
        insert into user(name,pwd) VALUES (#{name},#{pwd})
</insert>

4.万能Map

在实际开发中,我们经常会使用一个Map集合来接收参数,有人称之为“万能Map”,这样做有什么好处呢?

  • 当需要传递多个参数时,直接使用一个Map集合,可以避免出现错误,因为Mybatis传递多个参数的话,需要对每个参数加上@Param注解,有时候我们会忘记加上这个参数,导致出现错误,而使用万能Map就可以避免这个错误的发生

不使用万能Map的情况(多个参数没有加上@Param注解)

//UserMapper的部分代码
public User findByIdAndName(Integer id,String name);

//UserMapper.xml的部分代码
<select id="findByIdAndName" resultMap="userMap">
    select * from user where id=#{id} and name=#{name}
</select>

//测试代码
@Test
public void findByIdAndName(){
    SqlSession session = MybatisUtils.getSession();
    UserMapper mapper = session.getMapper(UserMapper.class);
    User user = mapper.findByIdAndName(1, "狂神");
    System.out.println(user); 
}
org.apache.ibatis.exceptions.PersistenceException: 
### Error querying database.  Cause: org.apache.ibatis.binding.BindingException: Parameter 'id' not found. Available parameters are [arg1, arg0, param1, param2]
### Cause: org.apache.ibatis.binding.BindingException: Parameter 'id' not found. Available parameters are [arg1, arg0, param1, param2]

不使用万能Map的情况(加上@Param注解)

public User findByIdAndName(@Param("id") Integer id,@Param("name") String name);
User(id=1, name=狂神, password=123456)

Process finished with exit code 0

需要注意的是:@Param注解括号里面声明的参数名要跟UserMapper.xml中SQL语句的参数名相同
在这里插入图片描述
在这里插入图片描述
使用万能Map的情况

//UserMapper的部分代码
public List<User> testLimit(Map<String,Integer> map);

//UserMapper.xml的部分代码
<select id="testLimit" parameterType="map" resultMap="userMap">
    select * from user limit #{startIndex},#{pageSize}
</select>

//测试代码
@Test
public void testLimit(){
    SqlSession session = MybatisUtils.getSession();
    UserMapper mapper = session.getMapper(UserMapper.class);
    Map<String,Integer> map=new HashMap<>();
    map.put("startIndex",0);
    map.put("pageSize",2);
    List<User> users = mapper.testLimit(map);
    for(User u:users){
        System.out.println(u);
    } 
}
User(id=1, name=狂神, password=123456)
User(id=2, name=张三, password=abcdef)

Process finished with exit code 0

由上面的例子可以看到,使用万能Map可以避免使用@Param注解;另外,我们可以发现万能Map的另一个好处是,使用万能Map作为参数的方法既可以用作是根据id查询,也可当做根据id和name查询,具体怎么用,取决于Map。

5.Mybatis关于多对一的处理

场景:一个老师对应多个学生,多个学生对应一个老师;站在学生的角度,学生与老师就是多对一的关系;

问题要求:查询所有学生信息,并且显示学生对应的老师信息

补充:

  • 一对一:数据库表的外键可以建立在任何一方;
  • 多对一:数据库表的外键建立在多的一方;
  • 多对多:数据库表的外键通过建立一张中间表来实现

teacher表
在这里插入图片描述
student表(tid是外键,参考teacher表的id列)
在这里插入图片描述

//teacher实体类
public class teacher {
    private Integer id;
    private Integer age;
    private String name;
}
//student实体类
public class student {
    private Integer id;
    private Integer age;
    private String name;
    private teacher t;
}
public interface studentMapper {
    public student getStudent();
}
<mapper namespace="com.kuang.dao.studentMapper">
    <!--按照结果嵌套处理(类似联表查询)-->
    <resultMap id="studentMap1" type="student">
        <id property="id" column="id"></id>
        <result property="age" column="age"></result>
        <result property="name" column="name"></result>
        <!--多对一,即成员变量是引用类型的情况-->
        <association property="t" column="tid" javaType="teacher">
            <id property="id" column="id"></id>
            <result property="age" column="age"></result>
            <result property="name" column="name"></result>
        </association>
    </resultMap>

    <select id="getStudent" resultMap="studentMap1">
        select * from student s,teacher t where s.tid=t.id
    </select>
</mapper>

关于resultMap的一些使用细节:

  • resultMap可以处理数据库字段名与java类属性名不一致的问题,比如:假设数据库表的一个字段名是id,而实体类对应的属性名是sid,那么必须使用resultMap进行结果映射<result property="sid" column="id"></result>,否则从数据库表查询出来的字段信息将无法封装到对应的实体类上
  • 如果sql语句指定了字段的别名,那么resultMap进行结果映射应该注意:“column”值对应的是数据库字段的别名,而不是原来的字段名

6.Mybatis关于一对多的处理

场景:一个老师对应多个学生,多个学生对应一个老师;站在老师的角度,老师与学生就是一对多的关系;

问题要求:查询所有老师信息,并且显示该老师对应的所有学生信息

//teacher实体类
public class teacher {
    private Integer id;
    private Integer age;
    private String name;
    private List<student> students;
}
//student实体类
public class student {
    private Integer id;
    private Integer age;
    private String name;
    private Integer tid;
}
public interface teacherMapper {
    public List<teacher> getTeacher();
}
<mapper namespace="com.kuang.dao.teacherMapper">
    <resultMap id="teacherMap" type="teacher">
        <id property="id" column="tid"></id>
        <result property="age" column="tage"></result>
        <result property="name" column="tname"></result>
        <collection property="students" ofType="student">
            <id property="id" column="sid"></id>
            <result property="age" column="sage"></result>
            <result property="name" column="sname"></result>
            <result property="tid" column="tid"></result>
        </collection>
    </resultMap>

    <select id="getTeacher" resultMap="teacherMap">
        select s.id sid,s.name sname,s.age sage,t.name tname,t.age tage,t.id tid from teacher t,student s where s.tid=t.id
    </select>
</mapper>

补充:

  • javaType:用来指定实体类中属性的类型
  • ofype:用来指定映射到List或者集合中的pojo类型,泛型中的约束类型

注意:如果关联的两个表有相同的字段名,在编写sql语句应该给相同名字的字段名设置别名,否则可能出现意想不到的错误!

7.Mybatis关于多对多的处理

(多对多的处理,类似于一对多,实质就是在一方的实体类中建立一个关联另一方的集合,至于要在哪一方的实体类建立一个关联另一方的集合,关键看你的需求;比如你的需求是:查询所有用户信息,包括用户所关联的角色信息,那么应该在用户实体类创建一个角色集合;而如果需求是:查询所有角色信息,包括角色所关联的用户信息,那么应该在角色实体类创建一个用户集合)

场景:一个用户可以有多个角色,一个角色可以对应多个用户;那么不管是站在用户的角度还是角色的角度,都是多对多的关系;

user表
在这里插入图片描述
role表
在这里插入图片描述
u_r(中间表,保存user和role的外键)
在这里插入图片描述
①问题要求:查询所有用户信息,包括用户所关联的角色信息

//用户实体类
public class User {
    private Integer id;
    private String name;
    private String pwd;
    private List<Role> roles;
}
//角色实体类
public class Role {
    private Integer id;
    private String roleName;
}
public interface UserMapper {

    //查询所有用户,包括用户所对应的角色信息
    public List<User> getUser();
}
<mapper namespace="com.kuang.dao.UserMapper">
    <resultMap id="userMap" type="user">
        <id property="id" column="id"></id>
        <result property="name" column="name"></result>
        <result property="pwd" column="pwd"></result>

        <collection property="roles" ofType="role">
            <id property="id" column="rid"></id>
            <result property="roleName" column="rname"></result>
        </collection>
    </resultMap>
    <select id="getUser" resultMap="userMap">
        select u.*,r.id as rid,r.role_name as rname from user u
         left join u_r ur on u.id=ur.uid
         left join role r on ur.rid=r.id
    </select>
</mapper>
	@Test
    public void test1(){
        SqlSession session = MybatisUtils.getSession();
        UserMapper mapper = session.getMapper(UserMapper.class);
        List<User> users = mapper.getUser();
        for(User u: users){
            System.out.println(u);
        }
        session.close();
    }
User(id=1, name=狂神, pwd=123456, roles=[Role(id=1, roleName=教师), Role(id=2, roleName=学生)])
User(id=2, name=张三, pwd=abcdef, roles=[Role(id=1, roleName=教师)])
User(id=3, name=李四, pwd=987654, roles=[])
User(id=4, name=我又来修改了!, pwd=123, roles=[])
User(id=5, name=哈哈, pwd=123, roles=[])
User(id=6, name=啊啊, pwd=123, roles=[])

②问题要求:查询所有角色信息,包括角色所关联的用户信息

//用户实体类
public class User {
    private Integer id;
    private String name;
    private String pwd;
}
//角色实体类
public class Role {
    private Integer id;
    private String roleName;
    private List<User> users;
}
public interface RoleMapper {

    //查询所有角色,包括角色所对应的用户
    public List<Role> getRole();
}
<mapper namespace="com.kuang.dao.RoleMapper">
    <resultMap id="roleMap" type="role">
        <id property="id" column="rid"></id>
        <result property="roleName" column="rname"></result>

        <collection property="users" ofType="user">
            <id property="id" column="id"></id>
            <result property="name" column="name"></result>
            <result property="pwd" column="pwd"></result>
        </collection>
    </resultMap>
    <select id="getRole" resultMap="roleMap">
        select r.id rid,r.role_name as rname,u.* from role r
         left join u_r ur on r.id=ur.rid
         left join user u on ur.uid=u.id;
    </select>
</mapper>
	@Test
    public void test1(){
        SqlSession session = MybatisUtils.getSession();
        RoleMapper mapper = session.getMapper(RoleMapper.class);
        List<Role> roles = mapper.getRole();
        for(Role r: roles){
            System.out.println(r);
        }
        session.close();
    }
Role(id=1, roleName=教师, users=[User(id=1, name=狂神, pwd=123456), User(id=2, name=张三, pwd=abcdef)])
Role(id=2, roleName=学生, users=[User(id=1, name=狂神, pwd=123456)])
Role(id=3, roleName=医生, users=[])

PS:如果sql语句是分成多行编写,记得在上一行的行尾或者换行后的行首多打一个空格,否则可能会出现错误!

8.动态SQL

什么是动态SQL?动态SQL就是指根据不同的条件生成不同的SQL语句

动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架(Hibernate),你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。

  • if:假设多个if符合条件,那么会拼接多个if的参数
// 根据传入的参数进行查询
public List<Blog> queryBlogIF(Map map);
 <select id="queryBlogIF" parameterType="map" resultType="blog">
        /*where 1=1是为了满足sql语句的完整性,使用where标签可以完美的解决这个问题*/
        select * from blog where 1=1
        <if test="id!=null">and id=#{id}</if>
        <if test="title!=null">and title=#{title}</if>
        <if test="author!=null">and author=#{author}</if>
        <if test="create_time!=null">and create_time=#{create_time}</if>
        <if test="views!=null">and views=#{views} </if>
</select>
  • where:只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除。(主要用在查询语句)
<select id="queryBlogIF" parameterType="map" resultType="blog">
        select * from blog
        <where>
            <if test="id!=null">id=#{id}</if>
            <if test="title!=null">and title=#{title}</if>
            <if test="author!=null">and author=#{author}</if>
            <if test="create_time!=null">and create_time=#{create_time}</if>
            <if test="views!=null">and views=#{views} </if>
        </where>
</select>
  • choose、when、otherwise:类似Java 中的 switch 语句,假设多个when符合条件,那么也只会拼接第一个when的参数
//根据传入的参数进行查询
public List<Blog> queryBlogChoose(Map map);
<select id="queryBlogChoose" parameterType="map" resultType="blog">
        select * from blog
        <where>
            <choose>
                <when test="id!=null">
                    id=#{id}
                </when>
                <when test="title!=null">
                    and title=#{title}
                </when>
                <when test="author!=null">
                    and author=#{author}
                </when>
                <when test="create_time!=null">
                    and create_time=#{create_time}
                </when>
                <otherwise></otherwise>
            </choose>
        </where>
</select>
  • set:set 元素可以用于动态包含需要更新的列,忽略其它不更新的列(主要用在更新语句)

以往我们更新表信息传入的参数是一个实体类,这种方式带来的弊端是:如果你只需要更新某些字段的值,那么会给实体类对应的属性设置值,而不需要更新值的字段对应的属性没有赋值,那么会使得数据库表相应的字段值被置为null

现在使用万能Map与动态SQL语句就可以解决上述的问题,我们需要更新哪些字段的值,只需要将对应的值赋给一个map集合,那些不需要更新值的字段值则没有变化,还是原来的值

//根据传入的参数进行更新
public int updateBlog(Map map);
<update id="updateBlog" parameterType="map">
        update blog
        <set>
            <if test="title">title=#{title},</if>
            <if test="author">author=#{author},</if>
            <if test="create_time">create_time=#{create_time},</if>
            <if test="views">views=#{views}</if> 
        </set>
        where id=#{id}
</update>
  • foreach:对集合进行遍历(尤其是在构建 IN 条件语句的时候)。例如:select * from blog where id in(1,2,3);
public List<Blog> queryForeach(Map map);
<select id="queryForeach" parameterType="map" resultType="blog">
        select * from blog where views IN
        <foreach collection="lists" item="views" open="(" separator="," close=")">
            #{views}
        </foreach>
</select>
//测试根据views集合进行
	@Test
    public void test() {
        SqlSession session = MybatisUtils.getSession();
        BlogMapper mapper = session.getMapper(BlogMapper.class);
        Map map = new HashMap();
        List<Integer> list=new ArrayList<>();
        list.add(100);
        list.add(200);
        list.add(300);
        map.put("lists",list);
        List<Blog> blogs = mapper.queryForeach(map);
        for(Blog b: blogs){
            System.out.println(b);
        }
        session.close();
    }

9.Mybatis的缓存

什么是缓存?

缓存是指存在内存中的数据,将用户经常查询的数据放在缓存(内存)中,用户查询数据就不用从磁盘上(关系型数据库数据文件)查询,从缓存中查询,从而提高查询效率,解决了高并发系统的性能问题。

为什么使用缓存?

减少和数据库的交互,减少系统开销,提高系统效率。

什么样的数据能使用缓存?

经常查询并且不经常改变的数据。

一级缓存

一级缓存也叫本地缓存,sqlsession级别,是默认开启的;即缓存只在一个sqlsession会话级别生效;

缓存失效的情况:

  • 增删改操作,可能会改变原来的数据,所以必定会刷新缓存(即使你增删改操作看起来并不跟缓存中的数据相关,也是会刷新缓存的)
  • 查询不同的东西
  • 查询不同的Mapper.xml
  • 手动清理缓存(session.clearCache())
	@Test
    public void test(){
        SqlSession session = MybatisUtils.getSession();
        UserMapper mapper = session.getMapper(UserMapper.class);
        User user1 = mapper.findUserById(1);
        System.out.println(user1);
        System.out.println("==========================");
        User user2 = mapper.findUserById(1);
        System.out.println(user2);
        session.close();
    }

在这里插入图片描述
可以看到,两次查询相同的值,只有第一次是从数据库获取的,第二次会直接从缓存获取!

二级缓存

二级缓存也叫全局缓存,一级缓存的作用域太低了,所以出现了二级缓存;二级缓存是基于namespace级别的缓存,一个名称空间,对应一个二级缓存;也可以说二级缓存是基于一个Mapper.xml级别的

二级缓存的工作原理:

  • 一个会话查询一条数据,这条数据就会被放在当前会话的一级缓存中
  • 如果会话关闭了,那么这个会话对应的一级缓存就没了
  • 也就是说,所有的数据都会先放在一级缓存中,只有当会话提交或关闭后,才会提交到二级缓存中
  • 新的会话查询信息,就可以从二级缓存中获取内容

一级缓存是默认开启的,二级缓存是需要手动开启的,开启二级缓存的步骤为:

①在mybatis全局配置文件中显示的开启全局缓存(虽然该属性默认是为true,但是为了提高代码的可读性,让别人知道要开启二级缓存了,所以最好显示的开启)

<!--显示的开启全局缓存-->
<setting name="cacheEnabled" value="true"></setting>

②在要开启二级缓存的Mapper.xml配置文件中开启

注意:如果cache标签没有自定义参数,那么使用的实体类必须实现序列化接口,否则会出错。

<cache/>

也可以自定义参数

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

③测试

	@Test
    public void test2(){
        SqlSession session1 = MybatisUtils.getSession();
        UserMapper mapper1 = session1.getMapper(UserMapper.class);
        User user1 = mapper1.findUserById(1);
        System.out.println(user1);
        session1.close();

        System.out.println("================================");

        SqlSession session2 = MybatisUtils.getSession();
        UserMapper mapper2 = session2.getMapper(UserMapper.class);
        User user2 = mapper2.findUserById(1);
        System.out.println(user2);
        session2.close();
    }

在这里插入图片描述
可以看到,第一个sqlsession关闭后,第二个sqlsession还是能使用缓存获取数据,因为两个sqlsession创建的都是同一个mapper。

缓存原理

在这里插入图片描述

@Test
    public void test3(){
        SqlSession session1 = MybatisUtils.getSession();
        UserMapper mapper1 = session1.getMapper(UserMapper.class);
        User user1 = mapper1.findUserById(1);
        System.out.println(user1);
        session1.close();//由于session1关闭了,所以id为1的用户被存到二级缓存了

        System.out.println("=====================================");

        SqlSession session2 = MybatisUtils.getSession();
        UserMapper mapper2 = session2.getMapper(UserMapper.class);
        User user2 = mapper2.findUserById(1);//先从二级缓存查找,找到了,直接返回
        System.out.println(user2);
        System.out.println("=====================================");

        User user3 = mapper2.findUserById(2);//由于当前的session2还没有关闭,所以id为2的用户被存在一级缓存,并没有存在二级缓存
        System.out.println(user3);
        System.out.println("=====================================");

        User user4 = mapper2.findUserById(2);//二级缓存找不到id为2的用户,一级缓存找到了
        System.out.println(user4);
        System.out.println("=====================================");

        User user5 = mapper2.findUserById(3);//第一次查找,二级缓存找不到,一级缓存也找不到,只能从数据库查找
        System.out.println(user5);
        System.out.println("=====================================");

        session2.close();
    }

10.补充

可以编写一个 生产随机ID的工具类,保证每个ID都是唯一的

public class IDUtils {

    public static String getID(){
        return UUID.randomUUID().toString().replaceAll("-","");
    }
}

关于mybatis的学习文档:https://mybatis.org/mybatis-3/zh/dynamic-sql.html

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值