Mybatis 延迟加载策略、缓存

实际开发过程中并不需要总在加载用户信息时就一定要加载他的账户信息。此时就需要延迟加载。

延迟加载:

先从单表查,需要时再从关联表查,提高查询性能,也叫懒加载

一对一(查账户时不急着一起查用户信息)
  • 首先配置SqlMapConfig.xml
    开启延迟加载
    <settings>
        <!--开启Mybatis支持延迟加载-->
        <setting name="lazyLoadingEnabled" value="true"/>
        <!--将积极加载改为消息加载即按需加载-->
        <setting name="aggressiveLazyLoading" value="false"></setting>
    </settings>
  • 再配置IAccountDao.xml
<!-- 定义封装account和user的resultMap -->
    <resultMap id="accountUserMap" type="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="user" 
        select="com.itheima.dao.IUserDao.findById">
        </association>
    </resultMap>

    <!-- 查询所有 -->
    <select id="findAll" resultMap="accountUserMap">
        select * from account
    </select>
  • 测试类(不使用User就不会查询)
    @Test
    public void testFindAll(){
        List<Account> accounts = accountDao.findAll();
    }
一对多(查用户时不急着一起查账户信息)

IUserDao.xml

    <!-- 定义User的resultMap-->
    <resultMap id="userAccountMap" type="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>
        <!-- 配置user对象中accounts集合的映射 -->
        <collection property="accounts" ofType="account" select="com.itheima.dao.IAccountDao.findAccountByUid" column="id"></collection>
    </resultMap>

    <!-- 查询所有 -->
    <select id="findAll" resultMap="userAccountMap">
        select * from user
    </select>

缓存

缓存就是把数据放在内存里,访问很快,但是就会导致和数据库里的数据不能保持一致,所以更新敏感的数据不能放在缓存里
Mybatis里的数据分为一级缓存二级缓存,一级缓存是自动放在SqlSession里的,除非SqlSession清空或关闭,不然就会从SqlSession里拿到同一个数据。

一级缓存(SqlSession测试)

同一个数据

    @Test
    public void testCache() throws IOException {
        User user1 = userDao.findById(41);
        System.out.println(user1);
        User user2 = userDao.findById(41);
        System.out.println(user2);
        System.out.println(user1==user2);//true
    }

不同数据

    @Test
    public void testCache() throws IOException {
        User user1 = userDao.findById(41);
        System.out.println(user1);
        sqlSession.clearCache();
        userDao=sqlSession.getMapper(IUserDao.class);
        User user2 = userDao.findById(41);
        System.out.println(user2);
        System.out.println(user1==user2);
    }

在查询前数据库更改、删除等操作数据,SqlSession会清空操作以防止脏读

    <update id="upDateUser" parameterType="user">
        update user set username=#{username},address=#{address} where id=#{id}
    </update>

再次查询前更改了数据库的数据,所以前后查询的数据不一样,sqlSession会灵活的把数据删掉

    @Test
    public void testCache() throws IOException {
        User user1 = userDao.findById(41);
        System.out.println(user1);
        user1.setUsername("set username");
        user1.setAddress("anhui");
        userDao.upDateUser(user1);
        User user2 = userDao.findById(41);
        System.out.println(user2);
        System.out.println(user1==user2);//false
    }

二级缓存

二级缓存是存在于同一个SqlSessionFactory里的不同SqlSession,并且会共用同一个数据,**而不是同一个地址
**
步骤分三步:

  1. SqlMapConfig.xml 文件开启二级缓存
<settings>
<!-- 开启二级缓存的支持 -->
<setting name="cacheEnabled" value="true"/>
</settings>
  1. Mapper 映射文件
<mapper namespace="com.itheima.dao.IUserDao">
<!-- 开启二级缓存的支持 -->
<cache></cache>
</mapper>
  1. 配置 statement 上面的 useCache 属性
<select id="findById" resultType="user" parameterType="int" useCache="true">
select * from user where id = #{uid}
</select>

测试
第二次查询没有sql语句执行,数据是从二级缓存拿的

 @Test
 public void testFirstLevelCache(){
 SqlSession sqlSession1 = factory.openSession();
 IUserDao dao1 = sqlSession1.getMapper(IUserDao.class);
 User user1 = dao1.findById(41);
 System.out.println(user1);
 sqlSession1.close();//一级缓存消失
 SqlSession sqlSession2 = factory.openSession();
 IUserDao dao2 = sqlSession2.getMapper(IUserDao.class);
 User user2 = dao2.findById(41);
 System.out.println(user2);
 sqlSession2.close();
 System.out.println(user1 == user2);
 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值