多对一和一对多的处理P21,P22

本文介绍了MyBatis中处理一对多关系的两种方式,包括多对一查询的子查询和联表查询方法。通过示例展示了如何在StudentMapper接口和XML配置中实现查询,并分析了各自的优缺点。同时,还展示了在Teacher实体类中的一对多关系处理,以及对应的XML配置和测试代码。重点讨论了`javaType`和`ofType`的区别,并提供了面试中可能遇到的相关技术点,如MySQL的InnoDB引擎、索引及优化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

多对一:

按照查询嵌套处理:

StudentMapper:(接口很简单需要返回一个List)

package com.Li.dao;

import com.Li.pojo.Student;
import org.apache.ibatis.annotations.Select;

import java.util.List;

public interface StudentMapper {

    //查询所有学生的信息,以及对应的老师的信息.难点在于写出对的sql
    public List<Student> getStudent();
}

StudentMapper.xml:(难点:嵌套查询,association是对对象的处理,相当于查询了两次之后拼接在了一起)

<?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.Li.dao.StudentMapper">

    <!--
  思路:
      1.查询所有的学生信息
      2.根据查询出来的学生的tid,寻找对应的老师! 子查询-->
    <select id="getStudent" resultMap="StudentTeacher">
        select * from mybatis.student
    </select>

    <resultMap id="StudentTeacher" type="Student">
        <result property="id" column="id"/>
        <result property="name" column="name"/>
        <!--  复杂的属性,我们需要单独处理 对象:association 集合:collection    这里javaType并不重要,主要是其余的三个  -->
        <association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/>
    </resultMap>

    <select id="getTeacher" resultType="Teacher">
        select * from mybatis.teacher where id = #{id}
    </select>


</mapper>

测试类增加的内容:

@Test
    public void testStudent(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();

        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
        List<Student> studentList = mapper.getStudent();
        for (Student student : studentList) {
            System.out.println(student);
        }


        sqlSession.close();
    }

 成功!

按照结果嵌套处理:

第二种方式的接口:

public List<Student> getStudent2();

StudentMapper.xml:详解可以看里面的注释。

 <!--按照结果嵌套处理-->
    <select id="getStudent2" resultMap="StudentTeacher2">
        select s.id sid,s.name sname,t.name tname
        from mybatis.student s,mybatis.teacher t
        where s.tid = t.id
    </select>

    <resultMap id="StudentTeacher2" type="Student">
        <result property="id" column="sid"/>
        <result property="name" column="sname"/>
    <!--由于老师的查询不是简单的字符类型,而是一个类(从pojo的Student可以知道),所以需要association-->
    <!--property是实体类的名字,也就是pojo里参数的实际名字。后面javaType就相当于返回类型,这次我们需要查的是Teacher当然返回的就是Teacher了。相当于套娃。Student里面套了一个Teacher-->
    <!--Teacher中property的内容是Teacher实体类中实际的参数名字,column同意都是数据库中列的名字-->
        <association property="teacher" javaType="Teacher">
            <result property="name" column="tname"/>
        </association>
    </resultMap>

在这里做一个小小的修改就可以测试了。

 成功!

个人感觉第二种方式比较易于理解,并且方便使用。

如果第一种方式要连接5个表的话,还需要多写5个select分散的语句再将他们连起来。

在做一件事的时候一定是分工明确的。sql就写sql,对应关系就搞对应关系,分工明确。实现高内聚。这样分块之后,可读性强,而且易于修改。

问题:我没有查询老师的id为什么结果会有老师的id???

这两种对应两种sql查询方式:

子查询

联表查询

一对多:

配置基础环境:很简单。

 创建moudule之后,复制06的这几个内容。pom.xml只需要导入一个lombox包就OK了

 修改实体类,变为一对多。以下分别是Student和Teacher

package com.Li.pojo;

import lombok.Data;

@Data
public class Student {
    private int id;
    private String name;
    private int tid;
}
package com.Li.pojo;

import lombok.Data;

import java.util.List;

@Data
public class Teacher {
    private int id;
    private String name;

    //一个老师拥有多个学生
    private List<Student> students;
}

编写这个

这个方式是我最喜欢的处理方式。

    <select id="getTeacher" resultMap="TeacherStudent">
        SELECT  s.id sid,s.name sname,t.name tname,t.id,tid
        from student s,teacher t
        where s.tid = t.id and t.id = #{tid}
    </select>

    <resultMap id="TeacherStudent" type="Teacher">
        <result property="id" column="tid"/>
        <result property="name" column="tname"/>
        <!--  复杂的属性,我们需要单独处理 对象:association 集合:collection
             javaType="" 指定属性的类型!
             集合中的泛型信息,我们使用ofType获取.简单来说,用collection的时候使用ofType不用javaType
             -->
        <collection property="students" ofType="Student">
            <result property="id" column="sid"/>
            <result property="name" column="sname"/>
            <result property="tid" column="tid"/>
        </collection>
    </resultMap>

注意看注释的内容。里面有解析。

创建测试文件:

    @Test
    public void Test(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();

        TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);
        Teacher teacher = mapper.getTeacher(1);
        System.out.println(teacher);


        sqlSession.close();
    }

测试成功!

 第二种方式:(个人不推荐)

接口代码:

//子查询的方式实现
    Teacher getTeacher2(@Param("tid") int id);

 TeacherMapper.xml:

 <select id="getTeacher2" resultMap="TeacherStudent2">
        select * from mybatis.teacher where id = #{tid}
    </select>

    <resultMap id="TeacherStudent2" type="Teacher">
        <collection property="students" javaType="ArrayList" ofType="Student" select="getStudentByTeacherId" column="id"/>
    </resultMap>

    <select id="getStudentByTeacherId" resultType="Student">
        select * from  mybatis.student where tid = #{tid}
    </select>

测试代码:

 

@Test
    public void Test2(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();

        TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);
        Teacher teacher = mapper.getTeacher2(1);
        System.out.println(teacher);


        sqlSession.close();
    }

成功!

小结:

javaType:实体类中属性的类型。也就是参数的数据类型

ofType:泛型中才会出现。值为泛型中的数据类型。如List<某某某>,那么ofType的值就是某某某。

面试高频:

  • Mysql引擎
  • InnoDB底层原理
  • 索引
  • 索引优化
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值