Mybatis如何解决循环依赖问题

news2024/11/24 10:32:48

1、Mybatis如何解决循环依赖问题

mybatis的循环依赖,即是mapper.xml里面的A查询的resultMap包含了B属性(B属性是通过子查询得到的),而B属性中又包含了A(B查询的resultMap中又包含了A的查询),就会造成A-B-A的情况。
实际的代码样例如下:

<?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.mapper.BlogMapper">
    <cache></cache>

    <resultMap id="blogMap" type="com.entity.Blog" autoMapping="true">
        <result column="title" property="title"></result>
        <collection property="comments" column="id" select="selectCommentsByBlogId">
        </collection>
    </resultMap>

    <resultMap id="commentMap" type="com.entity.Comment" autoMapping="true">
        <result column="title" property="title"></result>
        <association property="blog" column="blog_id" select="selectBlogById"></association>
    </resultMap>

    <select id="selectCommentsByBlogId" resultMap="commentMap">
        select * from  comment where blog_id = #{id}
    </select>

    <select id="selectBlogById" resultMap="blogMap">
        select * from  blog where id = #{id}
    </select>

</mapper>

package com.entity;

import java.io.Serializable;
import java.util.List;

public class Blog implements Serializable {
   private List<Comment> comments;
   private String title;
 

   public  Blog(){
   }
   
    public List<Comment> getComments() {
        return comments;
    }

    public void setComments(List<Comment> comments) {
        this.comments = comments;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }
}


package com.entity;

import java.io.Serializable;
import java.util.Date;

public class Comment implements Serializable {
    private int id;
    private String content;
    private Date date;

    private Blog blog;

    public Blog getBlog() {
        return blog;
    }

    public void setBlog(Blog blog) {
        this.blog = blog;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }
}


Mybatis中利用的是一级缓存、空占位符,和延迟加载来解决循环依赖问题的。

Mybatis 框架是一个轻量级的 ORM 框架,通常不会出现循环依赖问题。但是,如果在实际应用场景中出现了循环依赖的情况,Mybatis 也提供了一些解决方案,以下是其中两种:

  • 使用延迟加载(Lazy Loading)特性
    Mybatis 支持延迟加载,可以将对象的加载推迟到真正需要使用它时再进行加载,这样就可以避免一些不必要的依赖。具体实现方式是通过在 Mapper 文件中配置使用延迟加载的关联属性或集合属性。

    • 全局配置
    <settings>
          <!-- 开启延迟加载 -->
         <setting name="lazyLoadingEnabled" value="true"/>
    </settings>
    
    • 局部配置
      在和标签中修改"fetchType"属性的值
      fetchType = FetchType.EAGER 立即加载
      fetchType = FetchType.LAZY 延迟加载
<association property="idCard" column="card_id" select="com.ycy.mapper.IdCardMapper.findById" fetchType="eager">
  • 使用二级缓存(Second Level Cache)
    Mybatis 的二级缓存是在 SqlSessionFactory 层面上的,可以共享多个 SqlSession 实例之间的缓存数据。在使用二级缓存时,需要对每个需要缓存的 Mapper 进行配置,将其标识为需要开启缓存的 Mapper。这样在查询数据时,先从缓存中获取数据,如果缓存中不存在,则执行 SQL 查询,并将查询结果放入缓存中。

需要注意的是,虽然 Mybatis 提供了延迟加载和二级缓存等解决方案,但是过度地依赖这些特性可能会增加系统的复杂度和调试难度,因此在实际使用中需要根据具体情况进行选择和权衡。同时,在设计数据库表结构和应用程序架构时,应尽量避免出现循环依赖的情况,以确保系统的稳定性和可维护性。

2、一级缓存

一级缓存是SqlSession级别的缓存。在操作数据库时需要构造 sqlSession对象,在对象中有一个数据结构(HashMap)用于存储缓存数据。不同的sqlSession之间的缓存数据区域(HashMap)是互相不影响的

过程分析

  1. 第一次查询id为1 的用户,此时先去一级缓存查找,如果查找不到,则去数据库查询,把查询后的 结果存储到一级缓存中。
  2. 第二次查询id为1 的用户,此时先去一级缓存查找,如果查找到,则直接从一级缓存中把数据取出,不去查询数据库。
  3. 只要中间发生增删改操作,那么一级缓存就清空,默认开启一级缓存。

在这里插入图片描述

3、二级缓存

二级缓存是mapper级别的缓存,多个SqlSession去操作同一个Mapper的sql语句,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的

过程分析

  1. 第一次查询id为1 的用户,此时先去二级缓存查找,如果查找不到,则去数据库查询,把查询后的 结果存储到二级缓存中
  2. 第二次查询id为1 的用户,此时先去二级缓存查找,如果查找到,则直接从二级缓存中把数据取出,不去查询数据库
  3. 只要中间发生增删改操作,那么二级缓存就清空,二级缓存默认不开启,需要手动开启。

在这里插入图片描述

一级缓存和二级缓存的作用范围图

在这里插入图片描述

3.1、开启二级缓存

使用 Mybatis 的二级缓存需要进行以下配置:

  1. 开启全局缓存支持
    在 mybatis-config.xml 配置文件中配置如下内容:
<configuration>
  <settings>
    <setting name="cacheEnabled" value="true" />
  </settings>
</configuration>

其中,cacheEnabled 表示开启全局缓存支持。

  1. 配置 Mapper 接口开启缓存支持,在 Mapper.xml 文件中,可以针对每个 Mapper 接口进行配置,以标识某个 Mapper 接口需要使用二级缓存。例如:
<mapper namespace="com.example.mybatis.mapper.UserMapper">
  <cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
  <select id="getUserById" resultType="com.example.mybatis.model.User" useCache="true">
    select * from user where id = #{id}
  </select>
</mapper>

其中,cache 标签表示使用的缓存实现类,这里使用 Ehcache 作为缓存实现;useCache 属性表示是否启用二级缓存,这里设置为 true。

  1. 配置 Ehcache 缓存实现
    如果使用 Ehcache 作为缓存实现,则需要在项目中引入 Ehcache 相关依赖,并在 Ehcache 的配置文件 ehcache.xml 中进行配置。关于 Ehcache 的详细配置和使用方法可以参考 Ehcache 官方文档。

以上就是使用 Mybatis 二级缓存的配置方法。需要注意的是,二级缓存虽然可以提高查询性能,但也会增加系统的复杂度,因此在实际使用中需要根据具体情况进行选择和权衡。同时,在设计数据库表结构和应用程序架构时,应尽量避免出现循环依赖的情况,以确保系统的稳定性和可维护性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/685270.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【系统架构】第五章-软件工程基础知识(软件测试、净室软件工程、基于构件的软件工程、 软件项目管理)

软考-系统架构设计师知识点提炼-系统架构设计师教程&#xff08;第2版&#xff09; 软件测试 一、测试方法 以测试过程中程序执行状态为依据可分为静态测试&#xff08;ST&#xff09;和动态测试&#xff08;DT&#xff09; 以具体实现算法细节和系统内部结构的相关情况为根据…

【Leetcode60天带刷】day35——452. 用最少数量的箭引爆气球,435. 无重叠区间,763.划分字母区间

​ 题目&#xff1a; 452. 用最少数量的箭引爆气球 有一些球形气球贴在一堵用 XY 平面表示的墙面上。墙面上的气球记录在整数数组 points &#xff0c;其中points[i] [xstart, xend] 表示水平直径在 xstart 和 xend之间的气球。你不知道气球的确切 y 坐标。 一支弓箭可以沿着…

SuperMap GIS基础产品云GIS FAQ集锦(3)

SuperMap GIS基础产品云GIS FAQ集锦&#xff08;3&#xff09; 【iServer】如何自定义iServer服务能力文档中提供者的信息&#xff1f; 【解决办法】操作步骤如下&#xff1a; 1&#xff09;进入iServer管理界面&#xff0c;依次点击服务-服务接口&#xff1b; 2&#xff09;点…

PL SQL结构化编程

第一章、存储过程 1.1、概念 存储过程是一个命名的程序块&#xff0c;包括过程的名称、过程使用的参数&#xff0c;以及过程执行的操作。 &#xff08;类似于java中的一种函数&#xff0c;但是存在区别&#xff09; 可以指定输入参数&#xff0c;和输出参数。 1.2、创建存…

Elasticsearch 地理空间计算

地理位1置搜索&#xff1a;使用查询API进行搜索 1、Geo Distance Query Geo Distance Query是在给定的距离范围内搜索数据的查询。例如&#xff0c;可以搜索给定地理位置附近指定距离内的所有文档。 GET /my_index/_search {"query": {"bool" : {"fi…

基于Python+Django+mysql+html图书管理系统V2.0

基于PythonDjangomysqlhtml图书管理系统V2.0 一、系统介绍二、功能展示1.图书查询2.图书添加3.图书修改4.图书删除5.数据库 三、其它系统四、获取源码 一、系统介绍 该系统实现了图书查询、图书添加&#xff0c;图书修改、图书删除 运行环境&#xff1a;python3.7/mysql5.7以…

STM32单片机(八)DMA直接存储器存取----第二节:DMA直接存储器存取练习1(DMA数据转运)

❤️ 专栏简介&#xff1a;本专栏记录了从零学习单片机的过程&#xff0c;其中包括51单片机和STM32单片机两部分&#xff1b;建议先学习51单片机&#xff0c;其是STM32等高级单片机的基础&#xff1b;这样再学习STM32时才能融会贯通。 ☀️ 专栏适用人群 &#xff1a;适用于想要…

TiDB 7.1资源管控和Oceanbase 4.0多租户使用对比

作者&#xff1a; seiang 原文来源&#xff1a; https://tidb.net/blog/a33d3498 一、背景 TiDB和Oceanbase都是非常优秀的国产分布式数据库&#xff1b;公司从2021年第一套生产业务的TiDB集群落地&#xff0c;随着第一套TiDB生产集群的落地&#xff0c;主要面向不同的业务…

[230607] 阅读TPO69汇总|9:00-10:00

目录 TPO6601 5 事实信息题 7 推理题 9 句子插入题 10 小结题 TPO6602 5 修辞目的题 7 词汇题 tame 10 小结题 TPO6603 TPO6601 5 事实信息题 做题技巧&#xff1a;实词对应 定位在&#xff08;1&#xff09;spread the tines of their tongue apart when they ret…

Greenplum数据库优化器——新Path类型CdbMotionPath

Path表示了一种可能的计算路径&#xff08;比如顺序扫描或哈希关联&#xff09;&#xff0c;更复杂的路径会继承Path结构体并记录更多信息以用于优化。Greenplum为Path结构体(src/include/nodes/relation.h/Path)新加CdbPathLocus locus字段&#xff0c;用于表示结果元组在当前…

ConstraintLayout使用指南

ConstraintLayout ConstraintLayout 可让您使用扁平视图层次结构&#xff08;无嵌套视图组&#xff09;创建复杂的大型布局。它与 RelativeLayout 相似&#xff0c;其中所有的视图均根据同级视图与父布局之间的关系进行布局&#xff0c;但其灵活性要高于 RelativeLayout&#x…

【读书笔记】《软件工程导论》

目录 一、软件工程概述 二、启动阶段 三、计划阶段 四、实施阶段 五、收尾阶段 一、软件工程概述 软件危机&#xff1a;在计算机软件的开发和维护过程中遇到的一系列严重问题。 软件危机的产生与自身的特点有关&#xff0c;还与软件开发、管理的方法不正确有关。 软件危…

ELK 多用户登录

先搭建ELK集群环境 请移步至&#xff1a;FilebeatELK 搭建日志收集平台 ES开启TLS加密通信与身份认证 进入ES集群任意一台安装目录&#xff0c;生成ca证书 这里最好使用ES启动账号操作&#xff0c;证书生成过程中一直回车到完成&#xff0c;不要去输入密码。 # 生成CA证书 bi…

UNIX网络编程卷一 学习笔记 第二十一章 多播

单播地址标识单个IP接口&#xff0c;广播地址标识某个子网的所有IP接口&#xff0c;而多播地址标识一组IP接口。单播和广播是寻址方案的两个极端&#xff08;要么单个要么全部&#xff09;&#xff0c;多播则意在两者之间提供一种折衷方案。多播数据报只应由对它感兴趣的接口接…

【软考网络管理员】2023年软考网管初级常见知识考点(8)-广域网技术

涉及知识点 广域网交换方式&#xff0c;广域网流量控制&#xff0c;广域网链路层协议&#xff0c;广域网传输标准&#xff0c;软考网络管理员常考知识点&#xff0c;软考网络管理员网络安全&#xff0c;网络管理员考点汇总。 原创于&#xff1a;CSDN博主-《拄杖盲学轻声码》&a…

MATLAB——Matlab R2018b软件安装教程

Matlab R2018b软件安装教程 1.选中【Matlab R2018b】压缩包&#xff0c;鼠标右击选择【解压到Matlab R2018b】。 2.双击打开【Matlab R2018b】文件夹。 3.双击打开【R2018b_win64】文件夹。 4.选中【setup】可执行文件&#xff0c;鼠标右击选择【以管理员身份运行】。 5.选择【…

AQS源码分析——以ReentrantLock为例

AQS自身属性&#xff1a; private transient volatile Node head; private transient volatile Node tail; private volatile int state; Node属性&#xff1a; // 共享 static final Node SHARED new Node(); // 独占 static final Node EXCLUSIVE null; // 线程被…

360手机黑科技“位置穿越”功能修复 360手机位置穿越不能用了 360手机刷机

360手机黑科技“位置穿越”功能修复 360手机位置穿越不能用了 360手机刷机 参考&#xff1a;360手机-360刷机360刷机包twrp、root 360刷机包360手机刷机&#xff1a;360rom.github.io 【前言】 360手机&#xff0c;内置的黑科技“位置穿越”&#xff0c;引用高德地图&#xff…

基于NSGA-II算法的多目标多旅行商问题建模求解

基于NSGA-II算法的多目标多旅行商问题建模求解 1引言2多目标多旅行商问题3多目标遗传算法NSGA-II3.1 编码3.2选择&#xff08;锦标赛选择&#xff09;3.3 交叉&#xff08;顺序交叉&#xff09;3.4 变异3.5快速非支配排序3.5.1符号说明3.5.2快速非支配排序[^7][^6]3.5.3快速非支…

C语言王国探险记之变量的前世今生

王国探险记系列 文章目录&#xff08;2&#xff09; 前言 一、变量是什么&#xff1f; 二、变量如何定义&#xff1f; 注意&#xff1a;当你赋值小数的时候&#xff0c;编译器会自然认为你是一个double类型的&#xff0c;所以你在使用float类型的时候要在小数后面加个f&…