Mybatis延迟加载和查询缓存(3)

| aggressiveLazyLoading | 当设置为‘true’的时候,懒加载的对象可能被任何懒属性全部加载。否则,每个属性都按需加载。 | true \ false | true |

//例如

场合:

当只有部分记录需要关联查询其它信息时,此时可按需延迟加载,需要关联查询时再向数据库发出sql,以提高数据库性能。

当全部需要关联查询信息时,此时不用延迟加载,直接将关联查询信息全部返回即可,可使用resultType或resultMap完成映射。

二、查询缓存

====================================================================

Mybatis提供查询缓存,用于减轻数据压力,提高数据库压力。

Mybatis提供一级缓存和二级缓存。

在这里插入图片描述

在操作数据库时需要构造SqlSession对象,在对象中有一个数据结构(HashMap)用于缓存数据。

不同的SqlSession之间的缓存数据区域是互相不影响的。

Mybatis一级缓存的作用域是同一个SqlSession,在同一个sqlSession中两次执行相同的sql语句,第一次执行完毕会将数据库中查询的数据写到缓存(内存),第二次会从缓存中获取数据将不再从数据库查询,从而提高查询效率。当一个sqlSession结束后该sqlSession中的一级缓存也就不存在了。Mybatis默认开启一级缓存。

Mybatis二级缓存是多个SqlSession共享的,其作用域是mapper的同一个namespace,不同的sqlSession两次执行相同namespace下的sql语句且向sql中传递参数也相同即最终执行相同的sql语句,第一次执行完毕会将数据库中查询的数据写到缓存(内存),第二次会从缓存中获取数据将不再从数据库查询,从而提高查询效率。Mybatis默认没有开启二级缓存需要在setting全局参数中配置开启二级缓存。

1、一级缓存


在这里插入图片描述

第一次发起查询,先去找缓存中是否有id为1的用户信息,如果没有,从数据库中查询用户信息。

得到用户信息,将用户信息存储到一级缓存中。

第二次发起查询用户id为1的用户信息,先去缓存中是否有id为1的用户信息,缓存中有,直接从缓存中获取用户信息。

如果SqlSession去执行commit操作(执行插入、更新、删除),清空SqlSession中的一级缓存。目的是为了让缓存中存储的是最新的信息,避免脏读。

Mybatis默认支持一级缓存,不需要在配置文件中配置。

Mybatis内部存储缓存使用一个HashMap,key为hashCode+sqlId+Sql语句。value为从查询出来映射生成的java对象。

应用场景:

在这里插入图片描述

2、二级缓存


在这里插入图片描述

SqlSession1去查询用户id为1的用户信息,查询到用户信息会将查询数据存储到二级缓存中。

SqlSession2去查询用户id为1的用户信息,去缓存中找是否存在数据,如果存在直接从缓存中取出数据。

二级缓存区域是根据mapper的namespace划分的,相同namespace的mapper查询数据放在同一个区域,如果使用mapper代理方法每个mapper的namespace都不同,此时可以理解为二级缓存区域是根据mapper划分。

每次查询会先从缓存区域找,如果找不到从数据库查询,查询到数据将数据写入缓存。

Mybatis内部存储缓存使用一个HashMap,key为hashCode+sqlId+Sql语句。value为从查询出来映射生成的java对象

sqlSession执行insert、update、delete等操作commit提交后会清空缓存区域。

开启二级缓存:

在核心配置文件SqlMapConfig.xml中加入

| 描述 | 允许值 | 默认值 |

| — | — | — |

| cacheEnabled对在此配置文件下的所有cache 进行全局性开/关设置。 | true false | true |

要在你的Mapper映射文件中添加一行: ,表示此mapper

开启二级缓存。


二级缓存需要查询结果映射的pojo对象实现java.io.Serializable接口实现序列化和反序列化操作,注意如果存在父类、成员pojo都需要实现序列化接口。

为了将缓存数据取出执行反序列化,因为二级缓存存储介质多种多样,不一定在内存。

禁用二级缓存:


在statement中设置useCache=false可以禁用当前select语句的二级缓存,即每次查询都会发出sql去查询,默认情况是true,即该sql使用二级缓存。

刷新缓存(就是清空缓存):

设置statement配置中的flushCache=“true” 属性,默认情况下为true即刷新缓存,如果改成false则不会刷新。使用缓存时如果手动修改数据库表中的查询数据会出现脏读。

应用场景:

对于访问多的查询请求且用户对查询结果实时性要求不高,此时可采用mybatis二级缓存技术降低数据库访问量,提高访问速度,业务场景比如:耗时较高的统计分析sql、电话账单查询sql等。

实现方法如下:通过设置刷新间隔时间,由mybatis每隔一段时间自动清空缓存,根据数据变化频率设置缓存刷新间隔flushInterval,比如设置为30分钟、60分钟、24小时等,根据需求而定。

局限性:

mybatis二级缓存对细粒度的数据级别的缓存实现不好,比如如下需求:对商品信息进行缓存,由于商品信息查询访问量大,但是要求用户每次都能查询最新的商品信息,此时如果使用mybatis的二级缓存就无法实现当一个商品变化时只刷新该商品的缓存信息而不刷新其它商品的信息,因为mybaits的二级缓存区域以mapper为单位划分,当一个商品信息变化会将所有商品信息的缓存数据全部清空。解决此类问题需要在业务层根据需求对数据有针对性缓存。

案例

================================================================

在这里插入图片描述

UserMapper.java

package com.xbj.mapper;

import com.xbj.po.TUser;

import java.util.List;

/**

  • 延迟加载

*/

public interface UserMapper {

//延迟加载

List userIncludeOrder();

TUser findUserById(Integer id);

List findAll();

void deleteById(Integer id);

}

UserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>

SELECT * from t_user

SELECT * from t_order where uid=#{id}

SELECT * from t_user

SELECT * FROM t_user where id=#{id}

SELECT * from t_user

DELETE from t_user WHERE id=#{id}

pom.xml

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns=“http://maven.apache.org/POM/4.0.0”

xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”

xsi:schemaLocation=“http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd”>

4.0.0

groupId

dome02

1.0-SNAPSHOT

org.mybatis

mybatis

3.4.6

mysql

mysql-connector-java

5.1.47

junit

junit

4.12

log4j

log4j

1.2.14

sqlMapConfig.xml

<?xml version="1.0" encoding="UTF-8" ?>

log4j.properties

Global logging configuration

log4j.rootLogger=DEBUG, stdout

MyBatis logging configuration…

log4j.logger.org.mybatis.example.BlogMapper=TRACE

Console output…

log4j.appender.stdout=org.apache.log4j.ConsoleAppender

log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

TOrder.java

package com.xbj.po;

import java.io.Serializable;

import java.util.List;

/**

  • @Author:晓宇码匠

  • @Date:2019/6/21 0021

*/

public class TUser implements Serializable {

private int id;

private String username;

private String password;

private Integer age;

private List tOrders;

public List gettOrders() {

return tOrders;

}

public void settOrders(List tOrders) {

this.tOrders = tOrders;

}

public int getId() {

return id;

}

public void setId(int id) {

this.id = id;

}

public String getUsername() {

return username;

}

public void setUsername(String username) {

this.username = username;

}

public String getPassword() {

return password;

}

public void setPassword(String password) {

this.password = password;

}

public Integer getAge() {

return age;

}

public void setAge(Integer age) {

this.age = age;

}

@Override

public boolean equals(Object o) {

if (this == o) return true;

if (o == null || getClass() != o.getClass()) return false;

TUser tUser = (TUser) o;

if (id != tUser.id) return false;

if (username != null ? !username.equals(tUser.username) : tUser.username != null) return false;

if (password != null ? !password.equals(tUser.password) : tUser.password != null) return false;

if (age != null ? !age.equals(tUser.age) : tUser.age != null) return false;

return true;

}

@Override

public int hashCode() {

int result = id;

result = 31 * result + (username != null ? username.hashCode() : 0);

result = 31 * result + (password != null ? password.hashCode() : 0);

result = 31 * result + (age != null ? age.hashCode() : 0);

return result;

}

@Override

public String toString() {

return “TUser{” +

“id=” + id +

“, username='” + username + ‘’’ +

“, password='” + password + ‘’’ +

“, age=” + age +

‘}’;

}

}

TUser.java

package com.xbj.po;

import java.io.Serializable;

import java.util.List;

/**

  • @Author:晓宇码匠

  • @Date:2019/6/21 0021

*/

public class TUser implements Serializable {

private int id;

private String username;

private String password;

private Integer age;

private List tOrders;

public List gettOrders() {

return tOrders;

}

public void settOrders(List tOrders) {

this.tOrders = tOrders;

}

public int getId() {

return id;

}

public void setId(int id) {

this.id = id;

}

public String getUsername() {

return username;

}

public void setUsername(String username) {

this.username = username;

}

public String getPassword() {

return password;

}

public void setPassword(String password) {

this.password = password;

}

public Integer getAge() {

return age;

}

public void setAge(Integer age) {

this.age = age;

}

@Override

public boolean equals(Object o) {

if (this == o) return true;

if (o == null || getClass() != o.getClass()) return false;

TUser tUser = (TUser) o;

if (id != tUser.id) return false;

if (username != null ? !username.equals(tUser.username) : tUser.username != null) return false;

if (password != null ? !password.equals(tUser.password) : tUser.password != null) return false;

if (age != null ? !age.equals(tUser.age) : tUser.age != null) return false;

return true;

}

@Override

public int hashCode() {

int result = id;

result = 31 * result + (username != null ? username.hashCode() : 0);

result = 31 * result + (password != null ? password.hashCode() : 0);

result = 31 * result + (age != null ? age.hashCode() : 0);

return result;

}

@Override

public String toString() {

return “TUser{” +

“id=” + id +

“, username='” + username + ‘’’ +

“, password='” + password + ‘’’ +

“, age=” + age +

‘}’;

}

}

test.java

import org.apache.ibatis.io.Resources;

import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import org.junit.Before;

import org.junit.Test;

import com.xbj.mapper.UserMapper;

import com.xbj.po.TUser;

import java.io.IOException;

import java.io.InputStream;

import java.util.List;

/**

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Java开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

import org.apache.ibatis.io.Resources;

import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import org.junit.Before;

import org.junit.Test;

import com.xbj.mapper.UserMapper;

import com.xbj.po.TUser;

import java.io.IOException;

import java.io.InputStream;

import java.util.List;

/**

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

[外链图片转存中…(img-1LzNUugv-1715840539560)]

[外链图片转存中…(img-XOQZ6Xxc-1715840539560)]

[外链图片转存中…(img-vCPLkok9-1715840539560)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Java开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值