系列学习 SpringBoot 整合 Mybatis 之第 5 篇 —— <association> 标签实现一对一关联查询(级联查询)

编程入门 行业动态 更新时间:2024-10-09 21:24:46

系列学习 SpringBoot 整合 Mybatis 之第 5 篇 —— <association> <a href=https://www.elefans.com/category/jswz/34/1770160.html style=标签实现一对一关联查询(级联查询)"/>

系列学习 SpringBoot 整合 Mybatis 之第 5 篇 —— <association> 标签实现一对一关联查询(级联查询)

本篇博客基于前面几篇博客的基础上继续深入学习的:

一对一级联关系在开发中经常遇到。比如一个用户对应一条个人信息。在 mybatis 中,通过 <resultMap> 元素的子元素 <association> 处理这种一对一级联关系。

在 <association> 元素中通常使用以下属性。
property:指定映射到实体类的对象属性。
column:指定表中对应的字段(即查询返回的列名,用该字段去关联查询)。
javaType:指定映射到实体对象属性的类型。
select:指定引入嵌套查询的子 SQL 语句,该属性用于关联映射中的嵌套查询。

为了大家查阅信息方便,这里直接给出核心代码(有2种方式),如果有时间可以继续往后面看!

<!-- 一对一关联查询方式1 --><resultMap id="BaseResultMap_1" type="com.study.entity.StudentEntity"><id column="id" jdbcType="INTEGER" property="id" /><result column="student_no" jdbcType="VARCHAR" property="studentNo" /><result column="student_name" jdbcType="VARCHAR" property="studentName" /><result column="introduce" jdbcType="VARCHAR" property="introduce" /><!-- 一对一关联查询 --><associationproperty="infoEntity"column="student_no"javaType="com.study.entity.InfoEntity"select="com.study.dao.InfoEntityMapper.getByNo"/></resultMap><!-- 根据学号查询所有信息(主表信息和关联表信息) --><select id="getAllInfoByNo_1" parameterType="java.lang.String" resultMap="BaseResultMap_1">select * from t_studentwhere student_no = #{studentNo,jdbcType=VARCHAR}</select><!-- 一对一关联查询方式2 --><resultMap id="BaseResultMap_2" type="com.study.entity.StudentEntity"><id column="id" jdbcType="INTEGER" property="id" /><result column="student_no" jdbcType="VARCHAR" property="studentNo" /><result column="student_name" jdbcType="VARCHAR" property="studentName" /><result column="introduce" jdbcType="VARCHAR" property="introduce" /><!-- 一对一关联查询 --><association property="infoEntity" javaType="com.study.entity.InfoEntity"><id column="info_id" jdbcType="INTEGER" property="id" /><result column="info_student_no" jdbcType="VARCHAR" property="studentNo" /><result column="age" jdbcType="INTEGER" property="age" /><result column="sex" jdbcType="VARCHAR" property="sex" /></association></resultMap><!-- 根据学号查询所有信息(主表信息和关联表信息) --><select id="getAllInfoByNo_2" parameterType="java.lang.String" resultMap="BaseResultMap_2">select s.*,f.id as info_id,f.student_no as info_student_no,f.age,f.sexfrom t_student as sleft join t_info as fon s.student_no = f.student_nowhere s.student_no = #{studentNo,jdbcType=VARCHAR}</select>

 

详细内容如下

前面已经有了学生表:

CREATE TABLE `t_student` (`id` int(11) NOT NULL AUTO_INCREMENT,`student_no` varchar(50) DEFAULT NULL COMMENT '学号',`student_name` varchar(50) DEFAULT NULL COMMENT '学生姓名',`introduce` varchar(255) DEFAULT NULL COMMENT '自我介绍',PRIMARY KEY (`id`),KEY `student_no` (`student_no`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

接下来我们再创建一个学生信息表,并制造一些测试数据:

CREATE TABLE `t_info` (`id` int(11) NOT NULL AUTO_INCREMENT,`student_no` varchar(50) DEFAULT NULL COMMENT '学号,对应 t_student 的 student_no 字段',`age` int(11) DEFAULT NULL COMMENT '年龄',`sex` varchar(10) DEFAULT NULL COMMENT '性别',PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

我们先创建学生信息的实体类:

package com.study.entity;/*** @author biandan* @description 学生信息实体类* @signature 让天下没有难写的代码* @create 2021-05-11 下午 10:44*/
public class InfoEntity {private Integer id;private String studentNo;//学号private Integer age;//年龄private String sex;//性别@Overridepublic String toString() {return "InfoEntity{" +"id=" + id +", studentNo='" + studentNo + '\'' +", age=" + age +", sex='" + sex + '\'' +'}';}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getStudentNo() {return studentNo;}public void setStudentNo(String studentNo) {this.studentNo = studentNo;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}
}

然后,在 resources 目录下创建 InfoEntityMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis//DTD Mapper 3.0//EN" ".dtd">
<mapper namespace="com.study.dao.InfoEntityMapper"><resultMap id="BaseResultMap" type="com.study.entity.InfoEntity"><id column="id" jdbcType="INTEGER" property="id" /><result column="student_no" jdbcType="VARCHAR" property="studentNo" /><result column="age" jdbcType="INTEGER" property="age" /><result column="sex" jdbcType="VARCHAR" property="sex" /></resultMap><!-- 根据学号查询信息 --><select id="getByNo" parameterType="java.lang.String" resultMap="BaseResultMap">select * from t_infowhere student_no = #{studentNo,jdbcType=VARCHAR}</select></mapper>

在 dao 层创建接口:InfoEntityMapper

package com.study.dao;import com.study.entity.InfoEntity;
import com.study.entity.StudentEntity;
import org.apache.ibatis.annotations.Mapper;import java.util.List;
import java.util.Map;@Mapper //如果不在 dao 层增加 @Mapper 注解,就在启动类增加扫描 dao 层的包
public interface InfoEntityMapper {/*** 根据学号查询* @param studentNo* @return*/InfoEntity getByNo(String studentNo);}

 

然后在学生的主体类上,加上信息的实体类对象:

package com.study.entity;public class StudentEntity {//主键IDprivate Integer id;//学号private String studentNo;//姓名private String studentName;//自我介绍private String introduce;//学生信息实体类private InfoEntity infoEntity;@Overridepublic String toString() {return "StudentEntity{" +"id=" + id +", studentNo='" + studentNo + '\'' +", studentName='" + studentName + '\'' +", introduce='" + introduce + '\'' +", infoEntity=" + infoEntity +'}';}public InfoEntity getInfoEntity() {return infoEntity;}public void setInfoEntity(InfoEntity infoEntity) {this.infoEntity = infoEntity;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getStudentNo() {return studentNo;}public void setStudentNo(String studentNo) {this.studentNo = studentNo;}public String getStudentName() {return studentName;}public void setStudentName(String studentName) {this.studentName = studentName;}public String getIntroduce() {return introduce;}public void setIntroduce(String introduce) {this.introduce = introduce;}
}

然后我们修改 mybatis 的配置,启用延迟加载。即修改 resources 目录下的文件:mybatis-config.xml。在使用 MyBatis 嵌套查询方式进行关联查询时,使用 MyBatis 的延迟加载可以在一定程度上提高查询效率。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis//DTD Config 3.0//EN" ".dtd">
<configuration><!-- 全局配置参数 --><settings><!-- 使全局的映射器启用或禁用缓存。 --><setting name="cacheEnabled" value="true"/><!-- debug 模式打印 sql 语句 --><setting name="logImpl" value="STDOUT_LOGGING"/><!--在使用MyBatis嵌套查询方式进行关联查询时,使用MyBatis的延迟加载可以在一定程度上提高查询效率--><!--打开延迟加载的开关--><setting name= "lazyLoadingEnabled" value= "true"/><!--将积极加载改为按需加载--><setting name="aggressiveLazyLoading" value="false"/></settings></configuration>

 

然后,我们编写 Mybatis 的 xml 文件:StudentEntityMapper.xml (注意,这里只列出关键的代码,其它代码不罗列)(核心代码

<!-- 一对一关联查询方式1 --><resultMap id="BaseResultMap_1" type="com.study.entity.StudentEntity"><id column="id" jdbcType="INTEGER" property="id" /><result column="student_no" jdbcType="VARCHAR" property="studentNo" /><result column="student_name" jdbcType="VARCHAR" property="studentName" /><result column="introduce" jdbcType="VARCHAR" property="introduce" /><!-- 一对一关联查询 --><associationproperty="infoEntity"column="student_no"javaType="com.study.entity.InfoEntity"select="com.study.dao.InfoEntityMapper.getByNo"/></resultMap><!-- 根据学号查询所有信息(主表信息和关联表信息) --><select id="getAllInfoByNo_1" parameterType="java.lang.String" resultMap="BaseResultMap_1">select * from t_studentwhere student_no = #{studentNo,jdbcType=VARCHAR}</select><!-- 一对一关联查询方式2 --><resultMap id="BaseResultMap_2" type="com.study.entity.StudentEntity"><id column="id" jdbcType="INTEGER" property="id" /><result column="student_no" jdbcType="VARCHAR" property="studentNo" /><result column="student_name" jdbcType="VARCHAR" property="studentName" /><result column="introduce" jdbcType="VARCHAR" property="introduce" /><!-- 一对一关联查询 --><association property="infoEntity" javaType="com.study.entity.InfoEntity"><id column="info_id" jdbcType="INTEGER" property="id" /><result column="info_student_no" jdbcType="VARCHAR" property="studentNo" /><result column="age" jdbcType="INTEGER" property="age" /><result column="sex" jdbcType="VARCHAR" property="sex" /></association></resultMap><!-- 根据学号查询所有信息(主表信息和关联表信息) --><select id="getAllInfoByNo_2" parameterType="java.lang.String" resultMap="BaseResultMap_2">select s.*,f.id as info_id,f.student_no as info_student_no,f.age,f.sexfrom t_student as sleft join t_info as fon s.student_no = f.student_nowhere s.student_no = #{studentNo,jdbcType=VARCHAR}</select>

再次解读 <association> 元素中通常使用以下属性。
property:指定映射到实体类的对象属性。这里的 infoEntity 对应的是 StudentEntity 里 InfoEntity 的对象,一个字母都不能差,要一模一样!

javaType:指定映射到实体对象属性的类型。这里映射到 InfoENtity 的全限路经。

在方式1中,我们使用以下两个属性:
column:指定表中对应的字段(即查询返回的列名,用该字段去关联查询)。这里使用学号 studenNo 去关联查询。
select:指定引入嵌套查询的子 SQL 语句,该属性用于关联映射中的嵌套查询。这里直接调用 dao 层的 getByNo 方法获取查询结果。

在方式2中,我们直接把 InfoEntity 的属性罗列出来,需要注意的是,我们需要给 InfoEntity 的 id 、studen_no 起别名,否则会和 StudentEntity 的 id 、studen_no 冲突导致数据错乱!

 

然后,编写 dao 层的接口:

    StudentEntity getAllInfoByNo_1(String studentNo);StudentEntity getAllInfoByNo_2(String studentNo);

然后在业务层调用 dao 层接口,关键代码如下:

        //根据学号查询所有信息(主表信息和关联表信息)String studentNo = "12310";StudentEntity entity = studentEntityMapper.getAllInfoByNo_1(studentNo);System.out.println(entity.toString());System.out.println("********************************");//根据学号查询所有信息(主表信息和关联表信息)StudentEntity entity_2 = studentEntityMapper.getAllInfoByNo_2(studentNo);System.out.println(entity_2.toString());

启动测试,控制台输出:

方式 1 执行了2条SQL语句。方式 2 使用左关联查询,只执行了一条SQL语句。

==>  Preparing: select * from t_student where student_no = ? 
==> Parameters: 12310(String)
<==    Columns: id, student_no, student_name, introduce
<==        Row: 1, 12310, 张三, 你好啊
<==      Total: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2cae3a58]
JDBC Connection [com.mysql.jdbc.JDBC4Connection@6395a6fd] will not be managed by Spring
==>  Preparing: select * from t_info where student_no = ? 
==> Parameters: 12310(String)
<==    Columns: id, student_no, age, sex
<==        Row: 1, 12310, 18, 男
<==      Total: 1
StudentEntity{id=1, studentNo='12310', studentName='张三', introduce='你好啊', infoEntity=InfoEntity{id=1, studentNo='12310', age=18, sex='男'}}*************************************************************Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@30a97670] was not registered for synchronization because synchronization is not active
JDBC Connection [com.mysql.jdbc.JDBC4Connection@6395a6fd] will not be managed by Spring
==>  Preparing: select s.*,f.id as info_id,f.student_no as info_student_no,f.age,f.sex from t_student as s left join t_info as f on s.student_no = f.student_no where s.student_no = ? 
==> Parameters: 12310(String)
<==    Columns: id, student_no, student_name, introduce, info_id, info_student_no, age, sex
<==        Row: 1, 12310, 张三, 你好啊, 1, 12310, 18, 男
<==      Total: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@30a97670]
StudentEntity{id=1, studentNo='12310', studentName='张三', introduce='你好啊', infoEntity=InfoEntity{id=1, studentNo='12310', age=18, sex='男'}}

 

OK,一对一关联查询讲解到这。

 

更多推荐

系列学习 SpringBoot 整合 Mybatis 之第 5 篇 —— <association> 标签实现一对一关联查询(级联查询)

本文发布于:2024-03-23 23:05:30,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1743908.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:标签   级联   系列   Mybatis   SpringBoot

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!