MyBatis:关联查询

MyBatis

  • 前言
  • 关联查询
      • 懒加载
      • 对象为集合时的关联查询

在这里插入图片描述

前言

MyBatis:配置文件 文章中,最后介绍了可以使用 select 标签的 resultMap 属性实现关联查询,下面简单示例

关联查询

首先,先创建 association_role 和 association_user 两张数据表,并建立关联关系
表结构如图:
在这里插入图片描述
表信息如图:
在这里插入图片描述

在创建 association_user 表时需要添加 association_role 表的关联字段( role_id )
表结构如图:
在这里插入图片描述
表信息如图:
在这里插入图片描述

接着,创建与两张数据表一一映射的实体类 AssociationRole 和 AssociationUser

// AssociationRole
package cn.edu.MyBatisDemo.model;public class AssociationRole {private int id;private String role;public AssociationRole() {super();}public AssociationRole(int id, String role) {this.id = id;this.role = role;}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getRole() {return role;}public void setRole(String role) {this.role = role;}@Overridepublic String toString() {return "AssociationRole{" +"id=" + id +", role='" + role + '\'' +'}';}
}
// AssociationUser
package cn.edu.MyBatisDemo.model;public class AssociationUser {private int id;private String name;//添加 AssociationRole 属性private AssociationRole role; // AssociationRole -- 1:m -- AssociationUser (一对多关系)public AssociationUser(int id, String name, AssociationRole role) {this.id = id;this.name = name;this.role = role;}public AssociationUser() {super();}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public AssociationRole getRole() {return role;}public void setRole(AssociationRole role) {this.role = role;}@Overridepublic String toString() {return "AssociationUser{" +"id=" + id +", name='" + name + '\'' +", role=" + role +'}';}
}

然后,创建一个接口 AssociationUserMap ,声明获取指定用户信息的方法。同时,创建映射文件 AssociationUserMap.xml 实现接口方法

// 接口 AssociationUserMap
package cn.edu.MyBatisDemo.mapper;import cn.edu.MyBatisDemo.model.AssociationUser;public interface AssociationUserMap {public AssociationUser selectUserById(int id); // 获取指定用户的信息
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""https://mybatis.org/dtd/mybatis-3-mapper.dtd"><!-- 映射文件 AssociationUserMap.xml -->
<mapper namespace="cn.edu.MyBatisDemo.mapper.AssociationUserMap"><select id="selectUserById" resultMap="associationUser">SELECT user.id,user.name,user.role_id,role.roleFROM association_user USER,`association_role` roleWHERE user.role_id=role.id AND user.id=#{id}</select><!-- id 设置别名;type 指定类 --><resultMap id="associationUser" type="cn.edu.MyBatisDemo.model.AssociationUser" ><!-- 字段名对应的属性名 --><id column="id" property="id" /><result column="name" property="name" /><!-- 映射关联对象的属性 --><result column="role_id" property="role.id" /><result column="role" property="role.role" /></resultMap>
</mapper>

最后,测试结果

package cn.edu.MyBatisDemo.test;import cn.edu.MyBatisDemo.mapper.AssociationUserMap;
import cn.edu.MyBatisDemo.model.AssociationUser;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;public class AssociationTest {@Testpublic void test() throws IOException {//1.根据配置文件创建数据库连接会话的工厂类InputStream inputStream = Resources.getResourceAsStream("mybatis.xml");//获取工厂类SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);//2.通过工厂类获取数据库连接的会话SqlSession sqlSession = sqlSessionFactory.openSession();//3.通过 sqlSession 操作数据库try {AssociationUserMap userMap = sqlSession.getMapper(AssociationUserMap.class);//获取所有用户AssociationUser user = userMap.selectUserById(20230829);System.out.println(user);sqlSession.commit();} finally {sqlSession.close();}}
}

结果如图:
在这里插入图片描述

懒加载

懒加载( Lazy Loading ),是在使用所需数据时才进行加载,而不是直接加载所有关联数据。这有利于提高查询性能和减少资源消耗。当一个实体类中包含关联对象(如一对多、多对多关系)时,使用懒加载可以避免在查询主对象时立即加载所有关联对象的数据,而是等到真正需要访问关联对象时才进行加载。

简单示例:
在上面案例的基础上,先通过使用 association 标签实现分步关联查询,再进行配置懒加载

首先,再创建一个接口 AssociationRoleMap ,声明获取指定用户信息的方法。同时,创建映射文件 AssociationRoleMap.xml 实现接口方法

package cn.edu.MyBatisDemo.mapper;import cn.edu.MyBatisDemo.model.AssociationRole;public interface AssociationRoleMap {public AssociationRole selectRoleById(int id); // 获取指定用户的信息
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""https://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="cn.edu.MyBatisDemo.mapper.AssociationRoleMap"><select id="selectRoleById" resultType="associationRole">SELECT `id`,`role` FROM `association_role` WHERE `id`=#{id}</select>
</mapper>

接着,在映射文件 AssociationUserMap.xml 中,使用 association 标签实现关联查询。同时,修改 select 标签上的 SQL 语句

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""https://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="cn.edu.MyBatisDemo.mapper.AssociationUserMap"><select id="selectUserById" resultMap="associationUser"><!-- 对比:分步关联查询的 SQL 语句相对简单些 -->SELECT `id`,`name`,`role_id` FROM `association_user` WHERE `id`=#{id}</select><!-- id 设置别名;type 指定类 --><resultMap id="associationUser" type="cn.edu.MyBatisDemo.model.AssociationUser" ><!-- 字段名对应的属性名 --><id column="id" property="id" /><result column="name" property="name" /><!-- 映射关联对象的属性 --><!-- <result column="role_id" property="role.id" /> --><!-- <result column="role" property="role.role" /> --><!-- 也可以使用子标签 association 实现关联查询 --><!-- property = 添加 AssociationRole 属性 role ;select = 关联对象映射文件中的方法 id ;column = 外键 --><association property="role" select="cn.edu.MyBatisDemo.mapper.AssociationRoleMap.selectRoleById" column="role_id" ></association></resultMap>
</mapper>

然后,在 pom.xml 配置文件中添加依赖包。同时,在 resources 目录下创建 log4j.properties 资源文件。目的是生成日志文件,方便观察理解

<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.16</version>
</dependency>
#日志级别,分为八个级别( Off-关闭日志记录 > Fatal-严重错误 > Error-错误 > Warn-警告 > Info-运行信息 > Debug-调试 > Trace-低级信息 > All-所有日志记录)
#日志级别越高,过滤的信息越多#配置根节点
log4j.rootLogger=Debug,stdout,D
#配置控制台输出
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.Threshold=Error
##输出格式(%d %p [%1] %m %n——日期时间 类 路径 信息 换行)
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%l] %m %n#配置文件输出
log4j.appender.D=org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.Append=true
log4j.appender.D.File=./log4j.log
log4j.appender.D.Threshold=Debug
#输出格式
log4j.appender.D.layout=org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern=%d %p [%l] %m %n

随之,在 resources 目录下的 mybatis.xml 全局配置文件中进行配置懒加载

<!-- 懒加载配置 -->
<settings><setting name="LazyLoadingEnabled" value="true"/><setting name="aggressiveLazyLoading" value="false"/>
</settings>

最后,测试结果
1.只获取 association_user 中的 name 属性(只加载所需要的数据,其他数据不加载)
在这里插入图片描述
查看日志,结果如图:
在这里插入图片描述

2.分步关联查询(加载所有关联数据)
在这里插入图片描述
查看日志,结果如图:
在这里插入图片描述

对象为集合时的关联查询

当关联查询的对象为集合时,与上面案例的主要区别为使用的是 collection 标签,而不是 association 标签。

简单示例:
首先,在实体类 AssociationRole 中添加 users 属性
在这里插入图片描述

接着,分别在接口 AssociationUserMap 和 AssociationRoleMap 中添加相应的方法
在这里插入图片描述
在这里插入图片描述

然后,分别在映射文件 AssociationUserMap.xml 和 AssociationRoleMap.xml 中实现相应的方法。同时在 AssociationRoleMap.xml 配置关联映射
在这里插入图片描述
在这里插入图片描述

最后,测试结果
结果如图:
在这里插入图片描述

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

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

相关文章

Postgresql常用命令函数

1、string_agg()函数 1.1用法: string_agg(expression, delimiter)&#xff0c;参数类型(text, text) or (bytea, bytea)&#xff0c;返回类型和参数类型一致,第一个参数是字段名&#xff0c;第二个参数是样式&#xff0c;比如&#xff0c;或者#分隔。 1.2实战: SELECT * FR…

深入解析数据结构与算法之堆

文章目录 &#x1f966;引言&#xff1a;&#x1f966;什么是堆&#x1f966;大顶堆与小顶堆&#x1f9c4;大顶堆&#xff08;Max Heap&#xff09;&#x1f9c4;小顶堆&#xff08;Min Heap&#xff09; &#x1f966;堆的表示&#x1f9c4;数组表示&#xff1a;&#x1f9c4;…

设计模式总结-笔记

一个目标&#xff1a;管理变化&#xff0c;提供复用&#xff01; 两种手段&#xff1a;分解vs.抽象 八大原则&#xff1a; 依赖倒置原则&#xff08;DIP&#xff09; 开放封闭原则&#xff08;OCP&#xff09; 单一职责原则&#xff08;SRP&#xff09; Liskov替换原则&a…

C/C++内存管理(1):C/C++内存分布,C++内存管理方式

一、C/C内存分布 1.1 1.2 二、C内存管理方式 C可以通过操作符new和delete进行动态内存管理。 2.1 new和delete操作内置类型 int main() {int* p1 new int;// 注意区分p2和p3int* p2 new int(10);// 对*p2进行初始化 10int* p3 new int[10];// p3 指向一块40个字节的int类…

C#,数值计算——插值和外推,PolCoef的计算方法与源程序

1 文本格式 using System; namespace Legalsoft.Truffer { /// <summary> /// polynomial coefficients from polynomial values /// </summary> public class PolCoef { public PolCoef() { } /// <summary>…

【Linux】:共享内存

共享内存 一.原理二.创建共享内存1.shmget2.写一个共享内存代码 三.进行通信1.各种接口2.各接口使用代码3.一次简单的通信四.共享内存的特点 一.原理 直接原理 共享内存顾名思义就是共同使用的一块空间。 很明显操作系统需要对这块内存进行管理&#xff0c;那么就避免不了先描…

Python pip 镜像源设置指南

文章目录 Python pip 镜像源设置指南前言安装单个包使用PyPI镜像使用镜像升级 pip设为默认pip镜像结语 Python pip 镜像源设置指南 前言 平时在使用 pip 安装一些包的时候速度非常慢,本文介绍如何在 Python3 下设置 PyPI 设置镜像源,本文以给 Python3 设置清华 镜像源举例. …

2023.11.20使用flask做一个简单图片浏览器

2023.11.20使用flask做一个简单图片浏览器 功能&#xff1a; &#xff08;1&#xff09;输入指定路径&#xff0c;打开文件夹 &#xff08;2&#xff09;判断文件格式为图片 &#xff08;3&#xff09;在前端进行预览 &#xff08;4&#xff09;使用bootstrap进行简单美化 ma…

win11,引导项管理

1&#xff0c;打开cmd,输入msconfig 2,进入引导选项卡 3&#xff0c;删除不需要的引导项

【CSH 入门基础 9 -- 输出 csh 脚本中每一句命令】

文章目录 输出csh脚本中每一句命令 输出csh脚本中每一句命令 在 csh 或 tcsh 脚本中&#xff0c;如果你想要输出脚本中的每一句执行&#xff0c;你可以在脚本的开头使用 -v&#xff08;verbose&#xff09;选项。这个选项会使得 shell 在执行命令前先打印出来。 要在脚本中使…

蓝桥杯每日一题2023.11.21

题目描述 “蓝桥杯”练习系统 (lanqiao.cn) 题目分析 思路&#xff1a; 1.去重排序将其进行预处理 2.用gcd得到最简比值 3.用gcd_sub分别计算分子、分母的指数最大公约数 #include<bits/stdc.h> using namespace std; const int N 110; typedef long long ll; ll…

前端性能优化之LightHouse

优质博文&#xff1a;IT-BLOG-CN 一、LightHouse环境搭建 LightHouse是一款由Google开发的开源工具&#xff0c;用于评估Web应用程序的性能和质量。可以将其看作是一个Chrome扩展程序运行&#xff0c;或从命令行运行。为LightHouse提供一个需要审查的网址&#xff0c;它将针对…

V100 GPU服务器安装CUDNN教程

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

Go语言常用命令详解(三)

文章目录 前言常用命令go get示例参数说明 go install示例参数说明 go list示例 go mod示例参数说明 go work基本用法示例 go tool示例 go version示例 go vet示例 总结写在最后 前言 接着上一篇继续介绍Go语言的常用命令 常用命令 以下是一些常用的Go命令&#xff0c;这些命…

智能座舱架构与芯片- (14) 测试篇 上

一、 验证平台概要 1.1 测试软件方法论 “软件定义汽车” 的时代&#xff0c;软件在整车制造中的重要性日渐凸显。但不同于其他行业的软件开发&#xff0c;汽车行业有自己独特的软件开发要求。首先是需求严谨、需求层次复杂、需要通过专业的工具进行管理&#xff1b;其次开发…

数据中台之用户画像

用户画像应用领域较为广泛,适合于各个产品周期,从新用户的引流到潜在用户的挖掘、 从老用户 的培养到流失用户的回流等。通过挖掘用户兴趣、偏好、人口统计特征,可以 直接 作用于提升营销精准 度、推荐匹配度,最终提升产品服务和企业利润。还包括广告投放、产品布局和行业报…

从0开始学习JavaScript--深入理解JavaScript的async/await

JavaScript的异步编程在过去经历了回调地狱、Promise的引入&#xff0c;而今&#xff0c;通过async/await&#xff0c;让我们获得了更加优雅、可读性更高的异步编程方式。本文将深入探讨async/await的概念、用法&#xff0c;并通过丰富的示例代码展示其在实际应用中的威力。 理…

JVM垃圾收集器

什么是垃圾收集器 Java虚拟机的垃圾收集器是内存回收的具体实现&#xff0c;主要用于回收不再使用的对象&#xff0c;释放内存空间。Java虚拟机提供了多种垃圾收集器&#xff0c;不同的垃圾收集器适用于不同的场景和需求。 在C中&#xff0c;对象所占的内存在程序结束运行之前…

Windows to Go U盘系统制作(未测完成)

三、Windows U盘系统制作 1、下载windows镜像&#xff0c;并通过Windows To Go方式制作&#xff0c;具体选项参考下面截图 2、选择Windows版本 3、配置Windows 体验相关参数

STM32通用定时器产生PWM信号

STM32通用定时器产生PWM信号 PWM信号stm32定时器PWM生成模式PWM配置基本步骤PWM周期计算CubeMX配置代码展现 本期内容我将展示使用STM32通用定时器产生PWM信号&#xff0c;这里以定时器3通道3为例 PWM信号 如果还不懂的话&#xff0c;可以看看 &#xff1a; “蓝桥杯单片机学习…