Mybatis基础

1、一个简单的Mybatis程序

首先先看dao层的IUserDao
  • 该层是持久层。里面有一个接口,用于查询存在一些查询的方法。
package com.mybatis.dao;
import com.mybatis.domain.User;
import java.util.List;
public interface IUserDao {
    List<User> findAll();
}
再看domain层的User
  • 这里面是一个类,这个类用于存放与数据库表对应的属性,也就是咱们说的ORM ,对象关系映射
package com.mybatis.domain;
import java.io.Serializable;
import java.util.Date;
public class User implements Serializable {
    private Integer id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;
    //省略get、set和toString方法
}

接着看resources层的SqlMapConfig.xml
  • 这里是配置整个数据库的信息,这里面除了配置数据库的信息外,还要配置每一个dao层执行sql语句的文件。
<?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>
    <!--配置环境-->
    <environments default="mysql">
<!--        配置mysql环境-->
        <environment id="mysql">
<!--            配置事务类型-->
            <transactionManager type="JDBC"></transactionManager>
<!--            配置数据源(连接池)-->
            <dataSource type="POOLED">
<!--                配置数据库的基本信息-->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis?serverTimezone=GMT"/>
                <property name="username" value="root"/>
                <property name="password" value="111111"/>
            </dataSource>
        </environment>
    </environments>
<!--    指定映射配置文件的位置,映射配置文件指的是每一个dao独立的配置文件-->
    <mappers>
        <mapper resource="com/mybatis/dao/IUserDao.xml"/>
    </mappers>
</configuration>
  • IUserDao.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">
<mapper namespace="com.mybatis.dao.IUserDao">
    <select id="findAll" resultType="com.mybatis.domain.User">
        select * from  users
    </select>
</mapper>
测试类
public class MybatisTest {
    public static void main(String[] args)throws Exception {
//        1、读取配置文件
        InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
//        2、创建SqlSessionFactory工厂
        SqlSessionFactoryBuilder factoryBuilder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = factoryBuilder.build(in);
//        3、使用工厂生产SqlSession对象
        SqlSession session = factory.openSession();
//        4、使用SqlSession创建Dao接口的代理对象
        IUserDao userDao = session.getMapper(IUserDao.class);
//        5、使用代理对象执行方法
        List<User> users = userDao.findAll();
        for (User user:users){
            System.out.println(user);
        }
//        6、释放资源
        session.close();
    }
}

2、Mybatis中resultMap标签和sql标签的设置

  • IUserDao.xml
    其中的mapper标签中的namespace属性指的就是持久层中的接口,这里的sql语句都是对应这个接口中的方法,也就是指定了命名空间。在这里resultMap标签是查询结果的列名和实体类的属性名的对应关系,也就是说我们类中的属性名不一定和数据库中的保持一致,其中property配置的就是类中的属性名,column设置的就是数据库中表的字段名。在sql语句的标签中之前的,resultType变成了resultMap。sql标签中直接写的是就是sql语句,这个可以有效的避免重复的写sql相同代码,如果要引用sql标签中内容,在对应的语句中需要引用Include标签,具体的可以看下面的代码。
<?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">
<mapper namespace="com.mybatis.dao.IUserDao">
<!--    配置,查询结果的列名和实体类的属性名的对应关系-->
    <resultMap id="userMap" type="com.mybatis.domain.User">
<!--        主键字段对应-->
        <id property="userId" column="id"></id>
<!--        非主键字段对应-->
        <result property="userName" column="username"></result>
        <result property="userAddress" column="address"></result>
        <result property="userSex" column="sex"></result>
        <result property="userBirthday" column="birthday"></result>
    </resultMap>
    <sql id="defaultUser">
        select * from users
    </sql>
<!--    查询所有-->
    <select id="findAll" resultMap="userMap">
        <include refid="defaultUser"></include>
    </select>
    <select id="findById" parameterType="INT" resultMap="userMap">
        select * from users where id = #{uid}
    </select>
</mapper>

3、Mybatis的CRUD

  • IUserDao.xml配置文件如下:
  • 这里的数据库表的字段和类的属性名称要一样,否则不能识别,如果想要改名字,可以用resultMap 。
<?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">
<mapper namespace="com.mybatis.dao.IUserDao">
    <!--<resultMap id="" type="">
        <id property="" column=""></id>
        <result property="" column=""></result>
    </resultMap>-->
<!--    查询所有-->
    <select id="findAll" resultType="com.mybatis.domain.User">
        select * from  users
    </select>
<!--    保存用户-->
    <insert id="saveUser" parameterType="com.mybatis.domain.User" >
        insert into users(username,address,sex,birthday)values (#{username},#{address},#{sex},#{birthday});
    </insert>
<!--    更新用户-->
    <update id="updateUserById" parameterType="com.mybatis.domain.User">
        update users set username=#{username},address=#{address},sex=#{sex},birthday=#{birthday} where id=#{id};
    </update>
<!--    删除用户-->
    <delete id="deleteUserById" parameterType="java.lang.Integer">
        delete from users where id=#{id};
    </delete>
</mapper>

4、Mybatis的模糊查询以及其它操作

IUserDao.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">
<mapper namespace="com.mybatis.dao.IUserDao">
<!--    保存用户-->
    <insert id="saveUser" parameterType="com.mybatis.domain.User" >
        <!--保存后返回id值-->
        <selectKey keyProperty="id" keyColumn="id" resultType="int" order="AFTER">
            select last_insert_id();
        </selectKey>
        insert into users(username,address,sex,birthday)values (#{username},#{address},#{sex},#{birthday});
    </insert>
    <!--    模糊查询-->
    <select id="findByName" parameterType="string" resultType="com.mybatis.domain.User">
        <!--select * from users where username like "%${value}%";-->
        select * from users where username like #{username};
    </select>
<!--    查询总用户数-->
    <select id="findTotalUser" resultType="int">
        select count(id) from users;
    </select>
</mapper>

4、多表联合查询之一对一

数据库表
  • 用户表users
    在这里插入图片描述
  • 账户表account,其中账户表的uid为外键,指向的是用户表的主键id
    在这里插入图片描述
我们首先来看两个实体类,对应着两张表
  • User类
public class User implements Serializable {
    private Integer id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;

  • Account类:这里需要注意的是,在这里定义了一User的类。用于查询当前账户所属的用户信息。
public class Account implements Serializable {
    private Integer id;
    private  Integer uid;
    private String money;
    private  User user;
查看咱们的主要配置文件:IAccountDao.xml

在之前的文章中提到过resultMap这个标签,但是对于多表查询我们还需要嵌套一个association标签。因为我们主要查询的是账户信息,其次是附带的用户信息,所以将用户信息放在association标签内。其中的property就是咱们在Account类中定义的属性。接着就是SQL语句select u.*,a.id as aid,a.uid,a.money from account a,users u where u.id = a.uid。我们首先将两张表分别取别名,然后条件是id与uid相等,之后我们先查询出用户的所有信息,然后查询出账户的信息,哪张表放在前面都行。

<?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">
<mapper namespace="com.mybatis.dao.IAccountDao">
<!--    定义封装account和user的resultMap-->
    <resultMap id="accountUserMap" type="com.mybatis.domain.Account">
        <id property="id" column="aid"></id>
        <result property="uid" column="uid"></result>
        <result property="money" column="money"></result>
<!--        一对一关系映射,配置封装user的内容-->
        <association property="user" column="uid">
            <id property="id" column="id"></id>
            <result property="username" column="username"></result>
            <result property="address" column="address"></result>
            <result property="sex" column="sex"></result>
            <result property="birthday" column="birthday"></result>
        </association>
    </resultMap>
<!--    查询所有-->
    <select id="findAll" resultMap="accountUserMap">
        select u.*,a.id as aid,a.uid,a.money from account a,users u where u.id = a.uid
    </select>
</mapper>

在这里插入图片描述

5、多表联合查询之一对多

数据库表

  • 用户表users
    在这里插入图片描述
  • 账户表account,其中账户表的uid为外键,指向的是用户表的主键id
    在这里插入图片描述
我们首先来看两个实体类,对应着两张表
  • 1、User类
public class User implements Serializable {
    private Integer id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;
     //    一对多关系映射,主表实体应该包含所属从表的实体的集合
    private List<Account> accounts;

  • 2、Account类:这里需要注意的是,在这里定义了一User的类。用于查询当前账户所属的用户信息。
public class Account implements Serializable {
    private Integer id;
    private  Integer uid;
    private String money;
查看咱们的主要配置文件:IUserDao.xml
  • 这里与一对一查询不同的是在resultMap标签内嵌套了一个collection标签而不是association标签,这里的collection表示的是一个集合。这里需要注意一下ofType这个属性,这个属性表示的是这个集合中的成员的类型。如果没有别名的话,必须要用全限定类名。对于这里用的sql语句select * from users u left outer join account a on u.id = a.uid。采用左外查询方式,这个查询的好处是左边的user表会全部查出。
<?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">
<mapper namespace="com.mybatis.dao.IUserDao">
<!--    定义User的resultMap-->
    <resultMap id="userAccountMap" type="com.mybatis.domain.User">
        <id property="id" column="id"></id>
        <result property="username" column="username"></result>
        <result property="address" column="address"></result>
        <result property="sex" column="sex"></result>
        <result property="birthday" column="birthday"></result>
        <collection property="accounts" ofType="com.mybatis.domain.Account">
            <id property="id" column="aid" ></id>
            <result property="uid" column="uid"></result>
            <result property="money" column="money"></result>
        </collection>

    </resultMap>
<!--    查询所有-->
    <select id="findAll" resultMap="userAccountMap">
        select * from users u left outer join account a on u.id = a.uid
    </select>
    <select id="findById" parameterType="INT" resultType="com.mybatis.domain.User">
        select * from users where id = #{uid}
    </select>
</mapper>

在这里插入图片描述

6、多表联合查询之多对多

数据库表
  • 1、用户表
    在这里插入图片描述
  • 2、角色表
    在这里插入图片描述
  • 3、中间表
    在这里插入图片描述
    其中中间表的两个外键分别指向另外两个表的主键id,uid指向User中的id,rid指向role中的id
我们首先来看两个实体类,对应着两张表(无中间表)
  • 1、User类
public class User implements Serializable {
    private Integer id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;
  • 2、Role类
 private Integer roleId;
    private String roleName;
    private String roleDesc;
//    多对多的关系映射,一个角色可以赋予多个用户
    private List<User> users;
查看咱们的主要配置文件:IRoleDao.xml
  • 这里除了sql语句外,其余的都在之前的博客中提到过相关的配置标签的作用,这里不在强调。重点说一下sql语句。
<?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">
<mapper namespace="com.mybatis.dao.IRoleDao">
    <resultMap id="roleMap" type="com.mybatis.domain.Role">
        <id property="roleId" column="rid"></id>
        <result property="roleName" column="role_name"></result>
        <result property="roleDesc" column="role_desc"></result>
        <collection property="users" ofType="com.mybatis.domain.User">
            <id property="id" column="id"></id>
            <result property="username" column="username" ></result>
            <result property="address" column="address" ></result>
            <result property="sex" column="sex" ></result>
            <result property="birthday" column="birthday" ></result>
        </collection>
    </resultMap>
    <select id="findAll" resultMap="roleMap">
        select u.*,r.id as rid,r.role_name,r.role_desc from role r
         left outer join user_role ur on ur.rid =r.id
         left outer join users u on ur.uid = u.id
    </select>
</mapper>
  • 首先呢,我们必须通过角色表和中间表查询相关的信息组成一张新表:
    用 SELECT * FROM role r LEFT OUTER JOIN user_role ur ON ur.rid =r.id得到如下的表:
  • 大家可以看到在这个新表中,存在uid也就是指向我们用户表,然后将这个新表在与用户表联合左外查询便可得出结果:
    在这里插入图片描述
  • 这样就完成了多对多,由于新表中有重复的内容,所以我们改一下语句就是上面提到的
    在这里插入图片描述

7、延迟加载

  • 在之前的文章一对多中,当我们有一个用户,他又一百个账户。
    (1)在查询用户时,要不要把关联的账户信息查询出来?
    (2)在查询账户时,要不要把关联的用户信息查询出来?
  • 对于第一个问题,我们应该是什么时候需要查询账户信息,才查询。没必要每次查询用户信息都把账户信息也查询出来。因为如果每次都查询出账户信息,对我们的内存开销是很大的,而且每次查询也都不一定用到账户信息。
  • 对于第二个问题,我们就可以在查询账户信息的时候查询出关联的用户信息,因为我们如果只是单纯的账户信息没有说明用户是谁,这对于我们来说是不友好的。也没什么意义,所以在每次查询账户信息的时候都要显示出关联的用户信息。
延迟加载和立即加载
  • 第一个问题其实就是延迟加载。
    第二个问题就是立即加载。
延迟加载

在真正的使用数据时才发起查询,不用的时候不查。按需加载(懒加载)。

立即加载

不管用不用,只要一调用方法,马上发起查询。

四种对应的表关系中的加载
  • 四种表 关系:一对一,一对多,多对一,多对多。
  • 一对多、多对多:通常情况下,我们都是采用延迟加载。
  • 多对一、一对一:通常情况下,我们都是采用立即加载。
实现一对一的延迟加载

这里的项目结构和https://blog.csdn.net/weixin_44588495/article/details/91556447里面的大部分内容是一样的,我们只需要更改一些配置信息。

  • 更改IAccountDao.xml的配置信息
    这里将association标签中的内容全部删除,添加了一个select属性,select属性指向的是IUserDao接口的findById方法,也就是说执行这个sql语句后,就会执行findById这个方法,其中入口参数就是column中的uid这个值。
<?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">
<mapper namespace="com.mybatis.dao.IAccountDao">
<!--    定义封装account和user的resultMap-->
    <resultMap id="accountUserMap" type="com.mybatis.domain.Account">
        <id property="id" column="id"></id>
        <result property="uid" column="uid"></result>
        <result property="money" column="money"></result>
<!--        一对一关系映射,配置封装user的内容
        select 属性指定的内容,查询用户的唯一标识
        column 属性指定的内容,用户根据id查询时,所需要的参数的值
-->
        <association property="user" column="uid" javaType="com.mybatis.domain.User" select="com.mybatis.dao.IUserDao.findById"></association>
    </resultMap>
<!--    查询所有-->
    <select id="findAll" resultMap="accountUserMap">
        select * from account
    </select>
</mapper>
<?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>
<!--    配置参数-->
    <settings>
        <setting name="lazyLoadingEnabled" value="true"/>
        <setting name="aggressiveLazyLoading" value="false"/>
    </settings>
</configuration>
运行结果

未调用获取账户信息的方法。

  • 在MybatisAccountTest中调用
public  void testFindAll() throws Exception{
        List<Account> accounts = accountDao.findAll();
        for (Account a:accounts){
            System.out.println("-----------------------");
            System.out.println(a );
        }
    }

在这里插入图片描述
调用获取信息的方法

  • 在MybatisAccountTest中调用
public  void testFindAll() throws Exception{
        List<Account> accounts = accountDao.findAll();
        for (Account a:accounts){
            System.out.println("-----------------------");
            System.out.println(a );
            System.out.println(a.getUser());
        }
    }

在这里插入图片描述

实现一对多的延迟加载

这里的项目结构和https://blog.csdn.net/weixin_44588495/article/details/91556447里面的大部分内容是一样的,我们只需要更改一些配置信息。这里面的道理和一对一是一样的。只不过改的是collection标签内的属性。

  • 更改IUserDao.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">
<mapper namespace="com.mybatis.dao.IUserDao">
        <collection property="accounts" ofType="com.mybatis.domain.Account" select="com.mybatis.dao.IAccountDao.findAccountByUid" column="id"></collection>
</mapper>

IAccountDao接口:这里多增加了一个findAccountByUid方法

public interface IAccountDao {
    /**
     * 查询所有的Account
     * @return
     */
    List<Account> findAll();
    List<Account> findAccountByUid(Integer uid);
}

IAccountDao.xml中需要增加一条方法配置信息

<select id="findAccountByUid" resultType="com.mybatis.domain.Account" parameterType="Integer">
        select * from account where uid = #{uid}
</select>

SqMapConfig.xml文件和一对一是一样的。

运行结果:

未调用获取账户信息的方法。

  • 在MybatisTest中调用
public  void testFindAll() throws Exception{
        List<User> users = userDao.findAll();
        for (User user:users){
            System.out.println("--------------------------------------");
            System.out.println(user);
        }
    }

在这里插入图片描述
调用获取信息的方法

  • 在MybatisTest中调用
public  void testFindAll() throws Exception{
        List<User> users = userDao.findAll();
        for (User user:users){
            System.out.println("--------------------------------------");
            System.out.println(user);
            System.out.println(user.getAccounts());
        }
    }

在这里插入图片描述
这样就起到了该调用的时候调用,不用浪费多余的内存空间。

8、缓存

缓存

  • 存在与内存中的临时数据。

为什么使用缓存?

  • 减少和数据库的交互次数,提高执行的效率。

什么样的数据能使用缓存

  • 经常查询且不经常改变的
  • 数据的正确与否对最终结果影响不大的

什么样的数据不适用于缓存

  • 经常改变的数据
  • 数据的正确与否对最终结果影响很大的
  • 例如:商品的库存,银行的汇率,股市的牌价
一级缓存
  • 它指的是Mybatis中SqlSession对象的缓存,当我们执行查询之后,查询的结果同时会存入到SqlSession一块区域中,该区域的一个结构是Map结构。当我们再次查询同样的数据,mybatis会先去sqlsession中查询是否有,有的话直接拿来用。当SqlSession对象关闭时,或者清空缓存,mybatis的一级缓存也就消失了。
代码查看一级缓存
  • 表结构
    在这里插入图片描述
public class MybatisTest {
    private InputStream  in;
    private SqlSession session;
    private IUserDao userDao;
    private SqlSessionFactory factory;

    @Before
    public void init() throws Exception {
        this.in = Resources.getResourceAsStream("SqlMapConfig.xml");
        SqlSessionFactoryBuilder factoryBuilder = new SqlSessionFactoryBuilder();
        System.out.println(in);
        this.factory = factoryBuilder.build(in);
//        this.session = factory.openSession(true);
        this.session = factory.openSession();
        this.userDao = session.getMapper(IUserDao.class);
    }
    @After
    public void destory() throws IOException {
        session.commit();
        this.in.close();
        this.session.close();
    }
    @Test
    public void testCache(){
        User user1  = userDao.findById(8);
        System.out.println(user1);
        session.clearCache();
        User user2  = userDao.findById(8);
        System.out.println(user2);
        System.out.println(user1 == user2);
    }
}
  • 执行完testCache方法后,结果如下:
    在这里插入图片描述
    两个user对象是一样的,说明第一次从数据库中读取后,第二次直接拿的是session的一级缓存。
  • 当我们把testCache的方法改成如下两钟时
public void testCache(){
        User user1  = userDao.findById(8);
        System.out.println(user1);
        session.clearCache();
        User user2  = userDao.findById(8);
        System.out.println(user2);
        System.out.println(user1 == user2);
    }
public void testCache(){
        User user1  = userDao.findById(8);
        System.out.println(user1);
        session.close();
        session = factory.openSession();
        userDao = session.getMapper(IUserDao.class);
        User user2  = userDao.findById(8);
        System.out.println(user2);
        System.out.println(user1 == user2);
    }

此时已经将缓存session关闭或者清空缓存,结果如下:
在这里插入图片描述
此时两个User对象不同,说明是从数据库钟两次读取的结果。

一级缓存如何实现数据同步的呢?

一级缓存是SqlSession范围的缓存,当调用SqlSession的修改、添加、删除,commit(),close()等方法时,就会清空一级缓存。
这样如果更新了数据,就自动清空缓存,下一次读取的时候就在数据库中读取内容。

二级缓存
  • 它指的是Mybatis中SqlSessionFactory对象的缓存,由同一个SqlSessionFactory对象创建的SqlSession共享其缓存。
    在这里插入图片描述
二级缓存的使用步骤
  1. 第一步:让Mybatis框架支持二级缓存(在SqlMapConfig.xml中配置)
  2. 第二步:让当前的映射文件支持二级缓存(在IUserDao.xml中配置)
  3. 第三步:让当前的操作支持二级缓存(在Select标签中配置)
代码查看二级缓存
  • SqlMapConfig.xml
    添加setting标签
<?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>
<!--    配置参数-->
    <settings>
        <setting name="cacheEnabled" value="true"/>
    </settings>
</configuration>
  • IUserDao.xml
    添加一个cache标签 ,select标签中添加useCache=“true”
<?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">
<mapper namespace="com.mybatis.dao.IUserDao">
    <cache/>
    <select id="findById" parameterType="INT" resultType="com.mybatis.domain.User"  useCache="true">
        select * from users where id = #{uid}
    </select>
</mapper>
  • 测试类:
    sqlSession1.close();其中这个时关闭一级缓存对二级缓存的影响。
public void testCache(){
        SqlSession sqlSession1 = factory.openSession();
        IUserDao userDao1 = sqlSession1.getMapper(IUserDao.class);
        User user1 = userDao1.findById(8);
        System.out.println(user1);
        sqlSession1.close();

        SqlSession sqlSession2 = factory.openSession();
        IUserDao userDao2 = sqlSession2.getMapper(IUserDao.class);
        User user2 = userDao2.findById(8);
        System.out.println(user2);
        sqlSession2.close();
        System.out.println(user1 == user2);
    }
运行结果:

如果有日志的话,会看到该两次查询,只从数据库中查询了一次结果,然后从缓存中拿取。
在这里插入图片描述

  • user1 与 user2不相同的原因是,我们在数据库中存储的不是一个对象,而是一组数据,可以理解为json格式的数据,当有请求拿缓存中的数据时,直接将数据给他,然后创建出一个新的对象出来。所以虽然是从缓存中拿取,但是两次的对象肯定是不同的。这一点和一级缓存不同,一级缓存在缓存中存储的就是一个对象。有一个请求缓存过来时,直接用一个引用指向该对象。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值