Mybatis基础学习之多对一关系处理

前言

小伙伴们,大家好,我是狂奔の蜗牛rz,当然你们可以叫我蜗牛君,我是一个学习Java半年多时间的小菜鸟,同时还有一个伟大的梦想,那就是有朝一日,成为一个优秀的Java架构师。

这个Mybatis基础学习系列是用来记录我学习Mybatis框架基础知识的全过程 (这个系列是参照B站狂神的Mybatis最新教程来写的,由于是之前整理的,但当时没有发布出来,所以有些地方可能有错误,希望大家能够及时指正!)


之后我将尽量以两天一更的速度更新这个系列,还没有学习Mybatis3框架的小伙伴可以参照我的博客学习一下;当然学习过的小伙伴,也可以顺便跟我一起复习一下基础。最后,希望能够和大家一同进步吧!加油吧!少年们!

特别提醒:如果对Mybatis基础学习系列感兴趣,可以阅读本系列往期博客:
第一篇Mybatis基础学习之初识Mybatis
第二篇Mybatis基础学习之第一个Mybatis程序
第三篇Mybatis基础学习之CRUD增删改查
第四篇Mybatis基础学习之万能的Map和模糊查询
第五篇Mybatis基础学习之配置解析(上篇)
第六篇Mybatis基础学习之配置解析(下篇)
第七篇Mybatis基础学习之使用ResultMap解决字段名不一致
第八篇Mybatis基础学习之日志工厂的简单使用
第九篇Mybatis基础学习之数据分页的简单使用
第十篇Mybatis基础学习之使用注解开发
第十一篇Mybatis基础学习之Lombok的简单使用


今天我们来到了Mybatis基础学习的第十一站:多对一关系处理。废话不多说,让我们开始今天的学习内容吧。

11.多对一关系处理

11.1 多对一基本概念

什么是多对多关系

多对多关系图

在这里插入图片描述

例如上图,多个学生对应一个老师

对于学生这边而言,为关联关系,即多个学生,关联一个老师,这就是多对一关系

对于老师而言,为集合关系,即一个老师,包含多个学生,这就是一对多关系

11.2 编写SQL语句

11.2.1 创建teacher老师表

-- 创建teacher表
Create table `teacher` (
	`id` int(10) not null,
    `name` varchar(30) default null,
    primary key(`id`)
) engine=InnoDB default charset=utf8;-- 插入教师信息
Insert into teacher(`id`,`name`)values (1,'吕艳婷');

11.2.2 创建student学生表

-- 创建student表
Create table `student`(
	`id` int(10) not null,
    `name` varchar(30) default null,
    `tid` int(10) default null,
    primary key(`id`),
    key `fktid` (`tid`),
    constraint `fktid` foreign key(`tid`) references `teacher`(id)
) engine=InnoDB default charset=utf8;

-- 插入学生信息
Insert into `student`(`id`,`name`,`tid`)values
(1,'赵乾景',1),(2,'陈张太康',1),(3,'胡良伟',1),(4,'锦鲤',1),(5,'马正阳',1);

11.2.3 数据库表模型图

student表teacher表的关系如下:

在这里插入图片描述

11.3 复杂环境搭建初步测试

11.3.1 编写实体类和工具类

1.编写Teacher实体类
package com.kuang.pojo;

@Data // 引入无参构造、get、set、toString等方法
@AllArgsConstructor // 引入有参构造方法
@NoArgsConstructor // 引入无参构造方法

public class Teacher {
    
    private int id; // 教师编号
    private String name; // 教师姓名
    
}
2.编写Student实体类
package com.kuang.pojo;
@Data // 引入无参构造、get、set、toString等方法
@AllArgsConstructor // 引入有参构造方法
@NoArgsConstructor // 引入无参构造方法
public class Student {
    private int id; // 学生编号
    private String name; // 学生姓名
    // 学生需要关联一个老师
    private Teacher teacher;
}
3.编写MybatisUtils工具类
package com.kuang.utils;

/** 
 * SqlSessionFactoryBuilder(建造工厂)
 * --> sqlSessionFactory(生产sqlSession)
 * --> sqlSession  
 */
public class MybatisUtils {
    
    // 获取静态SQL会话工厂
    private static SqlSessionFactory sqlSessionFactory;
    // 静态方法体
    static {
        try {
            // 读取配置文件
            String resource = "mybatis-config.xml";
            // 解析配置文件流
            InputStream inputStream = Resources.getResourceAsStream(resource);
            // 获取工厂
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
   /**
    * SqlSession 提供了在数据库执行 SQL 命令所需的所有方法
    */
   public static SqlSession getSqlSession() {
       // 设置参数为true,实现自动提交
       return sqlSessionFactory.openSession(true);
   }
    
}

11.3.2 编写Mapper接口及其映射文件

1.编写TeacherMapper接口及其映射文件
1-1 编写TeacherMapper接口
package com.kuang.dao;

import com.kuang.pojo.Teacher;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;

public interface TeacherMapper {
    
    /**
     * 使用@Select注解: 通过用户id查询指定用户信息
     * (注意: SQL语句中的id与@Param注解中的一致)
     */
    @Select("Select * from teacher where id=#{tid}")
    Teacher getTeacher(@Param("tid") int id);
}
1-2 编写TeacherMapper.xml映射文件
  • resources文件目录下创建com.kuang.dao包

    在这里插入图片描述

  • 编写TeacherMapper.xml映射文件

<?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.kuang.dao.TeacherMapper">
    
</mapper>
2.编写StudentMapper接口及配置文件
1-1 编写StudentMapper接口
package com.kuang.dao;

public interface StudentMapper {
    
}
1-2 编写StudentMapper接口配置文件
  • resources文件目录下创建com.kuang.dao包,编写StudentMapper.xml映射文件
<?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.kuang.dao.StudentMapper">
    
</mapper>

11.3.3 编写核心配置文件

1.编写db.properties配置文件
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8
username=root
pwd=123456
2.编写mybatis-config.xml配置文件
2-1 使用resource资源路径绑定注册mapper接口
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<!-- configuration: 核心配置文件 -->
<configuration>
    
    <!-- 引入外部配置文件, 优先使用外部配置文件 -->
    <properties resource="db.properties"/>
    
    <!-- 设置标准日志输出 -->
    <settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
    
    <!-- 通过给包起别名 -->
    <typeAliases>
        <package name="com.kuang.pojo"/>
    </typeAliases>
    
    <!-- 设置默认环境为开发环境 -->
    <environments default="development">
        <!-- 设置一道环境为开发环境 -->
        <environment id="development">
            <!-- transactionManager: 表示事务管理器, 而MyBatis的默认管理器是JDBC-->
            <transactionManager type="JDBC"/>
            <!-- dataSource: 表示数据源, 主要作用: 连接数据库, MyBatis的默认数据源类型是POOLED,也就是有池的连接 -->
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${pwd}"/>
            </dataSource>
        </environment>
    </environments>
    
    <!--绑定接口:使用resource资源路径绑定注册-->
    <mappers>
       <mapper resource="com/kuang/dao/*Mapper.xml"/>
    </mappers>
    
</configuration>
2-2 使用class文件绑定注册mapper接口
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<!-- configuration: 核心配置文件 -->
<configuration>
    
    <!-- 引入外部配置文件, 优先使用外部配置文件 -->
    <properties resource="db.properties"/>
    
    <!-- 设置标准日志输出 -->
    <settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
    
    <!-- 通过给包起别名 -->
    <typeAliases>
        <package name="com.kuang.pojo"/>
    </typeAliases>
    
    <!-- 设置默认环境为开发环境 -->
    <environments default="development">
        <!-- 设置一道环境为开发环境 -->
        <environment id="development">
            <!-- transactionManager: 表示事务管理器, 而MyBatis的默认管理器是JDBC-->
            <transactionManager type="JDBC"/>
            <!-- dataSource: 表示数据源, 主要作用: 连接数据库, MyBatis的默认数据源类型是POOLED,也就是有池的连接 -->
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${pwd}"/>
            </dataSource>
        </environment>
    </environments>
    
    <!-- 绑定接口: 使用class文件绑定注册 -->
    <mappers>
        <mapper class="com.kuang.dao.TeacherMapper"/>
        <mapper class="com.kuang.dao.StudentMapper"/>
    </mappers>
    
</configuration>

11.3.4 创建编写测试类

1.编写测试类代码
package com.kuang.dao;

public class MyTest {
    
    	// 通过id查询指定老师信息
        @Test
        public void getTeacher() {
            // 获取SQlSession对象
            SqlSession sqlSession = MybatisUtils.getSqlSession();
            // 获取Mapper接口对象
            TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);
            // 通过id查询老师信息
            Teacher teacher = mapper.getTeacher(1);
		   // 打印查询的老师信息	
            System.out.println(teacher);
		   // 关闭SQLSession对象	
            sqlSession.close();
        }
    
}
2.测试结果
2-1 使用resource资源路径绑定注册接口

在这里插入图片描述

报错不能够找到resource资源路径:com/kuang/dao/*Mapper.xml

因此使用resource资源路径绑定注册接口时,不能使用通配符

2-2 使用class文件绑定注册mapper接口

在这里插入图片描述

结果成功查询到id为1的老师name为"吕艳婷"!

11.4 完善复杂环境搭建测试

11.4.1 创建编写实体类和工具类

  • 与11.3.1 的编写内容相同

11.4.2 创建编写Mapper接口及其映射文件

1.编写TeacherMapper接口及其映射文件
  • 与11.3.2中TeacherMapper接口及其映射文件的编写相同
2.编写StudentMapper接口及配置文件
  • 在11.3.2中编写的StudentMapperr接口及其映射文件基础上进一步修改
2-1 编写StudentMapper接口
package com.kuang.dao;
public interface StudentMapper {
    
    /** 
     * 查询所有的学生信息,以及对应的老师信息
     */
    // 按照查询嵌套处理
    public List<Student> getStudent();
    
    // 按照结果嵌套处理
    public List<Student> getStudent2();
    
}
2-2 编写StudentMapperx.xml映射文件
1.只使用select标签处理
<?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.kuang.dao.StudentMapper">
    
    <!-- 查询所有的学生信息(注意: 无法查询到对应的老师) -->
    <select id="getStudent" resultType="Student">
        Select * from student
    </select>
    
</mapper>
2.按照查询嵌套处理

思路

  • 查询所有的学生信息
  • 根据查询出来的学生的tid,寻找对应的老师,相当于子查询
<?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.kuang.dao.StudentMapper">
    
    <!-- 查询所有的学生信息 -->
    <select id="getStudent" resultMap="StudentTeacher">
        Select * from student
    </select>
    
    <!-- 结果映射集: 其中id对应select标签中resultMap的值, type对应Java实体类 -->
    <resultMap id="StudentTeacher" type="Student">
        <!-- column: 表示数据库中的字段名,property: 表示Java实体类中的属性名
             注意: 只需要显式定义不一致的字段和属性即可 -->
        <result column="id" property="id"/>
        <result column="name" property="name"/>
        <!-- 复杂的属性,需要单独处理, 其中association代表对象, 而collection代表集合;
             property的值teacher是对象,因此需要获取对象Teacher, 同时property又是一个复杂类型,需要给它一个类型, 因此使用javaType,值为对象Teacher;
             要让数据库列tid查出来是teacher, 因此要使用嵌套查询select -->
        <association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/>
    </resultMap>
    
    <!-- 通过id查询指定的老师信息 -->
    <select id="getTeacher" resultType="Teacher">
        Select * from teacher where id = #{id}
    </select>
    
</mapper>

知识扩充

association对象

collection集合

property注入给实体类的某个属性

column在上次查询结果集中,用哪些列值作为条件去执行下一条SQL语句

javaType把SQL语句查询出来的结果集,封装到某个类的对象(可以省略)

select下一条要执行的SQL语句

3.按照结果嵌套处理
<?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.kuang.dao.StudentMapper">
    
    <!-- 按照结果嵌套处理 -->
    <select id="getStudent2" resultMap="StudentTeacher2">
         Select s.id as sid,s.name as sname,t.name as tname
         from student s,teacher t
         where  s.tid = t.id
    </select>
    
    <!-- 结果集映射 -->
    <resultMap id="StudentTeacher2" type="Student">
        <!-- property表示Java类属性名, 而column表示数据库列名-->
        <result property="id" column="sid"/>
        <result property="name" column="sname"/>
        <!-- 复杂类型,需单独处理, 这里使用association, 代表集合;
             其他属性, 如property表示注入实体类Student的属性teacher; 
             javaType则表示返回的结果集,封装在Teacher类中-->
        <association property="teacher"  javaType="Teacher">
            <!-- 嵌套一个result
                 property表示Teacher类的属性名, 例如name
                 column表示对应数据库字段别名, 例如tname -->
            <result property="name" column="tname"/>
        </association>
    </resultMap>
    
</mapper>

11.4.3 创建编写核心配置文件

  • 与11.3.3核心配置文件的编写相同

11.4.4 创建编写测试类

1.编写测试类代码
package com.kuang.dao;

public class MyTest {
    
     /** 
      * 查询所有的学生信息
      */
    // 按照查询嵌套处理
    @Test
    public void getStudent() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
        List<Student> students = mapper.getStudent();
        for (Student student : students) {
            System.out.println(student);
        }
        sqlSession.close();
    }
    
     // 按照结果嵌套处理
    @Test
    public void getStudent2() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
        List<Student> students = mapper.getStudent2();
        for (Student student : students) {
            System.out.println(student);
        }
        sqlSession.close();
    }
    
}
2.测试结果
2-1 只使用select标签处理

在这里插入图片描述

结果虽然查询出了所有的学生信息,但teacher的值却为null!

2-2 按照查询嵌套处理

在这里插入图片描述

结果查询到了所有的学生信息,而且teacher的值也不为null值了!

2-3 按照结果嵌套处理

在这里插入图片描述

结果查询所有的学生信息成功,但是存在teacher的id为0的问题!

11.5 回顾MySQL多对一查询方式

11.5.1 子查询

Select id,name,tid
from student
where tid= (
    select ...);

11.5.2 联表查询

1.编写SQL语句
Select s.id,s.name,t.name
from student s,teacher t
where  s.tid = t.id
2.查询结果

在这里插入图片描述
结果成功查询到学生教师关联信息!


好了,今天的有关 多对一关系处理 的学习就到此结束啦。欢迎小伙伴们积极学习和讨论,喜欢的可以给蜗牛君点个关注,顺便来个一键三连。我们下期见,拜拜啦!


参考视频链接【狂神说Java】Mybatis最新完整教程IDEA版通俗易懂

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

狂奔の蜗牛rz

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值