首页 > 其他分享 >MyBatis学习日志五

MyBatis学习日志五

时间:2023-03-16 23:11:15浏览次数:31  
标签:缓存 信息 查询 学习 MyBatis 日志 延迟 id 加载

缓存
一级缓存

默认开启,同一个SqlSesion级别共享的缓存,在一个SqlSession的生命周期内,执行2次相同的SQL查询,则第二次SQL查询会直接取缓存的数据,而不走数据库,当然,若第一次和第二次相同的SQL查询之间,执行了DML(INSERT/UPDATE/DELETE),则一级缓存会被清空,第二次查询相同SQL仍然会走数据库

一级缓存在下面情况会被清除

在同一个SqlSession下执行增删改操作时(不必提交),会清除一级缓存
SqlSession提交或关闭时(关闭时会自动提交),会清除一级缓存
对mapper.xml中的某个CRUD标签,设置属性flushCache=true,这样会导致该MappedStatement的一级缓存,二级缓存都失效(一个CRUD标签在mybatis中会被封装成一个MappedStatement)
在全局配置文件中设置 <setting name="localCacheScope" value="STATEMENT"/>,这样会使一级缓存失效,二级缓存不受影响
二级缓存

默认关闭,可通过全局配置文件中的<settings name="cacheEnabled" value="true"/>开启二级缓存总开关,然后在某个具体的mapper.xml中增加<cache />,即开启了该mapper.xml的二级缓存。二级缓存是mapper级别的缓存,粒度比一级缓存大,多个SqlSession可以共享同一个mapper的二级缓存。注意开启二级缓存后,SqlSession需要提交,查询的数据才会被刷新到二级缓存当中

缓存的详细分析可以参考我之前的文章 => 极简mybatis缓存

关联查询
使用<resultMap> 标签以及<association>和<collection> 子标签,进行关联查询,比较简单,不多说

延迟加载
延迟加载是结合关联查询进行应用的。也就是说,只在<association>和<collection> 标签上起作用

对于关联查询,若不采用延迟加载策略,而是一次性将关联的从信息都查询出来,则在主信息比较多的情况下,会产生N+1问题,导致性能降低。比如用户信息和订单信息是一对多的关系,在查询用户信息时,设置了关联查询订单信息,如不采用延迟加载策略,假设共有100个用户,则我们查这100个用户的基本信息只需要一次SQL查询

select * from user;

若开启了关联查询,且不是延迟加载,则对于这100个用户,会发出100条SQL去查用户对应的订单信息,这样会造成不必要的性能开销(其实我认为称之为1+N问题更为合适)

select * from orders where u_id = 1;
select * from orders where u_id = 2;
....
select * from orders where u_id = 100;

当我们可能只关心id=3的用户的订单信息,则很多的关联信息是无用的,于是,采用延迟加载策略,可以按需加载从信息,在需要某个主信息对应的从信息时,再发送SQL去执行查询,而不是一次性全部查出来,这样能很好的提升性能。

另外,针对N+1问题,除了采用延迟加载的策略按需进行关联查询。如果在某些场景下,确实需要查询所有主信息关联的从信息。在上面的例子中,就是如果确实需要把这100个用户关联的订单信息全部查询出来,那怎么办呢?这里提供2个解决思路。

select * from user as u left join orders as o on u.id = o.u_id;

但使用连接查询查出来的结果是两表的笛卡尔积,还需要自行进行数据的分组处理

2是使用两个步骤来完成,先执行一条SQL,查出全部的用户信息,并把用户的id放在一个集合中,然后第二条SQL采用IN关键字查询即可。这种方式也可以简化为子查询,如下

select * from orders where u_id in (select id from user);

现在说回来,mybatis的延迟加载默认是关闭的,可以通过全局配置文件中的<setting name="lazyLoadingEnabled" value="true"/>来开启,开启后,所有的SELECT查询,若有关联对象,都会采用延迟加载的策略。当然,也可以对指定的某个CRUD标签单独禁用延迟加载策略,通过设置SELECT标签中的fetchType=eager,则可以关闭该标签的延迟加载。

(还有一个侵入式延迟加载的概念,在配置文件中通过<setting name="aggressiveLazyLoading" value="true">来开启,大概是说,访问主对象中的主信息时,就会触发延迟加载,将从信息查询上来,这其实并不是真正意义的延迟加载,真正意义上的延迟加载应该是访问主对象中的从信息时,才触发延迟加载,去加载从信息,侵入式延迟加载默认是关闭的,一般情况下可以不用管他)

注意,延迟加载在关联查询的场景下才有意义。需要配合<resultMap>标签下的<association>和<collecction> 标签使用

<!-- StudentMapper.xml -->
<resultMap id="studentExt" type="com.yogurt.po.StudentExt">
        <result property="id" column="id"/>
        <result property="name" column="name"/>
        <result property="score" column="score"/>
        <result property="age" column="age"/>
        <result property="gender" column="gender"/>
        <!-- 当延迟加载总开关开启时,resultMap下的association和collection标签中,若通过select属性指定嵌套查询的SQL,则其fetchType默认是lazy的,当在延迟加载总开关开启时,需要对个别的关联查询禁用延迟加载时,才有必要配置fetchType = eager -->
        <!--
         column用于指定用于关联查询的列
        property用于指定要封装到StudentExt中的哪个属性
        javaType用于指定关联查询得到的对象
        select用于指定关联查询时,调用的是哪一个DQL
        -->
        <association property="clazz" javaType="com.yogurt.po.Clazz" column="class_id"
                     select="com.yogurt.mapper.ClassMapper.findById" fetchType="lazy"/>

    </resultMap>

    <select id="findLazy" parameterType="string" resultMap="studentExt">
        SELECT * FROM student WHERE name like '%${value}%';
    </select>
<!-- com.yogurt.mapper.ClassMapper -->
<select id="findById" parameterType="int" resultType="com.yogurt.po.Clazz">
        SELECT * FROM class WHERE id = #{id}
</select>
/** 用于封装关联查询的对象 **/
public class StudentExt{

    private Integer id;

    private String name;

    private Integer score;

    private Integer age;

    private Integer gender;

    /** 关联对象 **/
    private Clazz clazz;
    
       //getter/setter
}

 

标签:缓存,信息,查询,学习,MyBatis,日志,延迟,id,加载
From: https://www.cnblogs.com/yzx-sir/p/17224591.html

相关文章

  • 3.16学习总结
    2.3.3Button(按钮)与ImageButton(图像按钮)分类 Android基础入门教程本节引言:今天给大家介绍的Android基本控件中的两个按钮控件,Button普通按钮和ImageButton图像按钮......
  • AS学习日记23.3.16
    今天学习了侧滑界面制作的布局文件写法和java文件的写法,准备之后学跳转实现学习了view和viewgroup了解了安卓中的六大布局:LinearLayout(线性布局),RelativeLayout(相对布......
  • arduino学习(1)
    买的Arduino板子终于到了,终于可以动手做实验了...  上图中有面包板,面包线,面包板电源,Arduino电路板,平多多买的,官网买会比较贵。  买的一块esp232板子......
  • MyBatis
    MyBatis1.编写流程1、编写工具类如:MybatisUtils(里面需要一个配置文件mybatis-config.xml)​ 主要是为了获取SqlSessionFactory,以及从中获得SqlSession的实例2、编......
  • TinyML 科研课堂学习笔记
    嵌入式微型机器学习与系统应用week1任务每周/隔周汇报进展(PPT)final:确定研究方向与主体开展研究工作参考arduinotinymlCS249r工作周期研究方向研究问题研......
  • 动手学深度学习v2——第六章predict_ch6
    在QA环节,有位同学问了第六章的predict函数在哪,书中没有给出,使用predict_ch3稍作更改可得。defpredict_ch6(net,test_iter,device,n=6):#@save"""预测标签(定义......
  • 点分治 学习笔记
    新知识+1。0x00前言点分治适合处理大规模的树上路径信息问题。0x01引入我们通过洛谷的模板题来引入点分治的概念:P3806【模板】点分治1:给定一棵有n个点的带边......
  • 日志
    2022.2.11今天主要学习了状压dp和树形dp。小知识:for循环中使用registerint可以卡常数对double类型的数memset赋值成127相当于无穷大poj不能用万能头,必须开longlong......
  • 概率论与数理统计及其应用学习笔记1(numpy+matplotlib)
    先把基本概念都理一遍,博客的后半部分会上具体函数实现,没有前半部分的基础,后半部分看起来会有点吃力样本空间:某个实验的所有可能结果组成的集合样本点:样本空间的每个结......
  • 06.深度学习--分类模型
    分类模型输入对象x,输出是这个对象属于哪一个类class,这样的应用同样有很多,比如:在金融上可以通过分类模型来决定是否贷款给某人;图像识别方面;人脸辨识方面,等等。这里依然使......