• 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;
        }
    
        @Override
        public String toString() {
            return "AssociationRole{" +
                    "id=" + id +
                    ", role='" + role + '\'' +
                    '}';
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    // 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;
        }
    
        @Override
        public String toString() {
            return "AssociationUser{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    ", role=" + role +
                    '}';
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

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

    // 接口 AssociationUserMap
    package cn.edu.MyBatisDemo.mapper;
    
    import cn.edu.MyBatisDemo.model.AssociationUser;
    
    public interface AssociationUserMap {
        public AssociationUser selectUserById(int id); // 获取指定用户的信息
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    
    DOCTYPE mapper
            PUBLIC "-//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">
            SELECT user.id,user.name,user.role_id,role.role
                FROM association_user USER,`association_role` role
                    WHERE user.role_id=role.id AND user.id=#{id}
        select>
    
        
        <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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    最后,测试结果

    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 {
        @Test
        public 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();
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

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

    懒加载

    懒加载( 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); // 获取指定用户的信息
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    
    DOCTYPE mapper
            PUBLIC "-//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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

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

    
    DOCTYPE mapper
            PUBLIC "-//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">
        	
            SELECT `id`,`name`,`role_id` FROM `association_user` WHERE `id`=#{id}
        select>
    
        
        <resultMap id="associationUser" type="cn.edu.MyBatisDemo.model.AssociationUser" >
            
            <id column="id" property="id" />
            <result column="name" property="name" />
    
            
            
            
    
            
            
            <association property="role" select="cn.edu.MyBatisDemo.mapper.AssociationRoleMap.selectRoleById" column="role_id" >association>
        resultMap>
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

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

    
    <dependency>
      <groupId>log4jgroupId>
      <artifactId>log4jartifactId>
      <version>1.2.16version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    #日志级别,分为八个级别( 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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

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

    
    <settings>
        <setting name="LazyLoadingEnabled" value="true"/>
        <setting name="aggressiveLazyLoading" value="false"/>
    settings>
    
    • 1
    • 2
    • 3
    • 4
    • 5

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

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

    对象为集合时的关联查询

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

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

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

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

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

  • 相关阅读:
    Some App Tech Support 一些应用技术支持
    【C++基础】2. 标准库
    动态内存分配【C语言】
    Vue3.js:自定义组件 v-model
    BAT学习——批处理脚本(也称为BAT文件)常用语法元素与命令
    SpringBoot 条件注解之:自定义条件注解
    jenkins配置用户权限分配角色和视图(三)
    Linux运维10:scp命令详解
    在centos上安装Anaconda
    GBase 8s gcadmin之addnodes命令解析
  • 原文地址:https://blog.csdn.net/qq_56886142/article/details/132452975