6.2 、MyBatis 高级映射(resultMap 标签多表联查 , 一对多,多对一关系)



一、创建表结构,添加数据,实现表中数据的关联关系


  • 数据的关联关系:

    • 一个班级中,有多名学生,一个班主任以及其他很多科任教师

      • 对于学生而言,多个学生,关联一个班主任,每个学生都和班主任有着关联关系 --【多对一

      • 班级中,有一名学生上课睡觉,被班主任抓个正着,拎出来训话 --【一对一

      • 对于班主任而言,一个班主任管理着一个班级,而班级中有很多学生 --【一对多

      • 一个班级中的每天都有不同的课程,不同的课程对应不同的教师 --【多对多


  • 表结构搭建
    -- 创建教师表
    CREATE TABLE IF NOT EXISTS `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, '柳神');
    
    -----------------------------------------------------------------
    --创建学生表
    CREATE TABLE IF NOT EXISTS `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);
    
    



二、 association 标签:用于一对一、多对一场景使用


  • association 标签属性:

    • property :配置实体类属性名

    • javaType :指定封装结果的类型。当使用 select 属性时,无需指定关联的类型,结果会直接封装到调用的查询语句中

    • column :配置数据库列名,搭配 select 属性使用,从第一条 SQL 中获取当前指定字段的内容,在将该内容传入 select 属性调用的 SQL 中

    • select :使用另一个select查询封装的结果。当使用该属性时,无需配置实体类与数据库之间的映射关系

  • association 标签的子标签:< id >< result >, 作用和 resultMap 标签的子标签一致



1、实现一对一,多对一关系结果集映射

       实现联表查询的方式有两种,一种是按照查询嵌套处理,一种是按照结果嵌套处理。通常来讲按照结果嵌套处理比较灵活,代码看起来也更加简洁。

1.1 按照查询嵌套处理

       该方式的执行流程:先执行第一个被调用的 < select > 标签语句,查询出结果后通过 < association > 标签的 column 获取结果中指定字段的值,在通过 select 调用第二个 < select > 标签语句 ,将 column 获取到的值传入该标签语句中,实现类似于子查询的操作,最后将第一个被调用的标签语句查询出的结果封装到 < resultMap > 的 type 属性当中,将第二个被调用的标签语句封装到 < association > 标签的 property 所指定的实体类属性当中,以此来实现结果集的映射。



  • 根据表创建对应的实体类

    • 创建 Student 实体

      @Alias("Student")  // 引用 mybatis-config.xml 中的实体类路径别名,这样再次引用时候直接引用别名就可以找到全路径了
      @Data  // 自动生成 get()、set()等方法
      public class Student {
      
          private Integer id;
          private String name;
          private String tid;
      
          // 关联教师实体,形成一对一,多对一的关联关系,将查询结果封装到该属性中
          private Teacher teacher;
      }
      
    • 创建 Teacher 实体

      @Data
      @Alias("Teacher")
      public class Teacher {
      
          private Integer id;
          private String name;
      }
      
    • 创建 StudentMapper

      public interface StudentMapper {
      
          List<Student> getStudent();
      }
      
    • 创建 XML

       	<select id="getStudent" resultMap="StudentMap">
              select * from student
          </select>
      	
          <resultMap id="StudentMap" type="Student">
              <result column="id" property="id"/>
              <result column="name" property="name"/>
      
              <!-- 查询完第一条查询SQL之后,通过association标签的column属性获取对应字段的值,将该值传入select属性所指定的查询SQL中,
              根据条件查询完之后将结果封装到property属性所指定的实体bean的属性中。  -->
              <association property="teacher" column="tid" select="getTeacher"/>
          </resultMap>
      
          <select id="getTeacher" resultType="Teacher">
              select * from teacher where id = #{tid}
          </select>
      
    • 代码运行结果
      在这里插入图片描述




1.2 按照结果嵌套处理(推荐)

       直接使用多表联查的形式去查询数据,通过 result 标签的属性将 SQL 语句中的字段和实体类形成映射关系,再通过 association 标签的 property 属性将 Teacher 实体中的 name 属性与 Student 实体的 teacher 属性值形成映射,以此来完成返回值映射。
  • 实体类不变,StudentMapper 接口中新增查询方法

    public interface StudentMapper {
    
        List<Student> getStudent();
    
        List<Student> getStudentAndTeacher();
    
    }
    
  • XML

    <resultMap id="StudentAndTeacher" type="Student">
            <result property="id" column="id"/>
            <result property="name" column="name"/>
    
            <!-- 将查询结果映射到 Teacher 实体类中 -->
            <association property="teacher" javaType="Teacher">
                <result property="name" column="name"/>
            </association>
        </resultMap>
    
        <select id="getStudentAndTeacher" resultMap="StudentAndTeacher">
            select   s.id as 学生编号, s.name as 学生姓名, s.tid as 班级编号, t.id as 教师编号,t.name as 教师姓名
    	        from student s,
    	             teacher t
    	        where s.tid = t.id
        </select>
    
  • 运行结果:
    在这里插入图片描述




三、 collection 标签:用于一对多、多对多场景使用(实体里放集合)

  • collection 标签属性:

    • property :实体类属性名

    • select :使用另一个select查询封装的结果。当使用该属性时,便不需要在配置实体类与数据库之间的映射关系了

    • column :为数据库中的列名,与select配合使用

    • ofType :指定集合中的泛型信息

  • collection 标签的子标签:< id >,< result >, 作用和 resultMap 标签的子标签一致


1、实现一对多,多对多关系结果集映射


1.1 按照查询嵌套处理

       该方式的执行流程和 association 大致相同,区别为,association 是通过学生共有的班级编号匹配班主任的教师编号,是多对一的关系。而 collection 是通过教师编号去匹配班级编号相同的学生,是一对多关系。

  • 根据表创建对应的实体类

    • 创建 Student 实体

      @Alias("Student")  
      @Data  
      public class Student {
      
          private Integer id;
          private String name;
          private String tid;
      }
      
    • 创建 Teacher 实体

      @Data
      @Alias("Teacher")
      public class Teacher {
      
          private Integer id;
          private String name;
          
          // 实现老师对应学生的 一对多关联关系
          private List<Student> student;
      }
      
    • 创建 TeacherMapper

      public interface TeacherMapper {
      
         //通过教师编号查询与之关联的学生
         List<Teacher> getManyToOne(int id);
      }
      
    • 创建 XML

      <select id="getManyToOne" resultMap="getManyToOne">
          select * from teacher where id = #{id}
      </select>
      
      <resultMap id="getManyToOne" type="Teacher">
          <result property="id" column="id"/>
          <result property="name" column="name"/>
          <collection property="student" javaType="ArrayList" select="getStudent" column="id"/>
      </resultMap>
      
      <select id="getStudent" resultType="Student">
          select * from student where tid = #{id}
      </select>
      
    • 代码运行结果
      在这里插入图片描述




1.2 按照结果嵌套处理(推荐)

  • 实体类不变,TeacherMapper 接口中新增查询方法

    public interface TeacherMapper {
    
        List<Teacher> getManyToOne(int id);
    
        List<Teacher> getManyToOne2(int id);
    }
    
  • XML

       <resultMap id="getManyToOne2" type="Teacher">
            <result property="id" column="id"/>
            <result property="name" column="name"/>
            <collection property="student" ofType="Student">
                <result column="id" property="id"/>
                <result column="name" property="name"/>
                <result column="tid" property="tid"/>
            </collection>
        </resultMap>
    
        <select id="getManyToOne2" resultMap="getManyToOne2">
            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>
    
  • 运行结果:
    在这里插入图片描述



  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: MybatisResultMap可以用来映射一对多关系。在ResultMap,可以使用collection标签来定义一个集合属性,用来表示一对多关系。在集合属性,可以使用result标签来定义子对象的映射规则。例如: <resultMap id="userMap" type="User"> <id property="id" column="id"/> <result property="name" column="name"/> <collection property="orders" ofType="Order"> <id property="id" column="order_id"/> <result property="name" column="order_name"/> </collection> </resultMap> 在上面的例子,User对象包含一个orders属性,用来表示一个用户可以有多个订单。使用collection标签来定义orders属性,并使用ofType属性来指定子对象的类型为Order。在集合属性,使用id和result标签来定义子对象的映射规则。这样,在查询结果,就可以将多个订单映射到一个User对象的orders属性。 ### 回答2: 在MyBatisResultMap是一种用于将查询到的结果集映射Java对象的机制。当查询结果集包含多个对象的属性时,就需要使用ResultMap一对多映射一对多映射的实现,需要在ResultMap定义一个collection元素来表示将多个对象映射成一个集合。collection元素需要设置property、ofType和select等属性。 property属性表示映射到结果集的查询条件,也就是查询多个对象时需要根据哪个属性进行关联。 ofType属性表示集合元素的类型,这里表示集合元素的类型为哪个Java类。 select属性表示查询的语句,对应于查询结果集的collection列。 例如,以下是一段使用ResultMap实现一对多映射的示例代码: <resultMap id="UserMap" type="User"> <id column="id" property="id"/> <result column="username" property="username"/> <result column="password" property="password"/> <collection property="books" ofType="Book" select="selectBooksByUser" column="id"/> </resultMap> 在上面的代码,UserMap是一个ResultMap配置,books是User类的一个List<Book>类型属性。通过collection元素的配置,表示User对象与多个Book对象之间存在一对多关系。 需要注意的是,以上的示例代码,还需要在mapper文件定义selectBooksByUser语句,用于查询对应的Book对象。同时,需要配置查询语句的查询条件,也就是column属性,与User对象的id属性关联起来。 通过以上的配置,如果查询结果集包含了User对象与多个Book对象,MyBatis就会根据配置进行自动映射,将查询结果集的数据转化为Java对象的形式,方便我们进行业务逻辑的处理。 ### 回答3: MyBatis是一种轻量级的ORM框架,支持复杂的SQL查询。其ResultMapMyBatis非常重要的一种映射规则,可以将查询结果映射Java对象。 在MyBatis,使用ResultMap进行一对多映射时,可以通过以下步骤完成: 1. 定义主实体类和从实体类 在一对多映射,主实体类代表一端,从实体类代表多端。例如,在一个学校的管理系统,Student代表主实体类,Grade代表从实体类。一名学生可以拥有多个成绩单。 2. 在主实体类增加从实体类的集合 在主实体类增加从实体类的集合属性,如下所示: public class Student { private int id; private String name; private List<Grade> grades; } 3. 定义ResultMap 定义ResultMap时,需要使用collection标签映射从实体类的集合属性。注意,collection标签的属性property应该指向主实体类的集合属性,同时需要指定从实体类的ResultMap,如下所示: <resultMap id="studentResultMap" type="Student"> <id property="id" column="id"/> <result property="name" column="name"/> <collection property="grades" ofType="Grade" resultMap="gradeResultMap"/> </resultMap> 4. 定义从实体类的ResultMap 在从实体类的ResultMap,需要定义每一列的映射关系。同样地,需要定义id标签,指向主实体类的外键列,如下所示: <resultMap id="gradeResultMap" type="Grade"> <id property="id" column="id"/> <result property="subject" column="subject"/> <result property="score" column="score"/> <association property="student" javaType="Student"> <id property="id" column="student_id"/> <result property="name" column="student_name"/> </association> </resultMap> 5. 编写查询语句 最后,编写查询语句时,需要使用select标签,并在其指定ResultMap,如下所示: <select id="getStudent" resultMap="studentResultMap"> SELECT s.id, s.name, g.id, g.subject, g.score, g.student_id, s2.name as student_name FROM student s LEFT JOIN grade g on s.id = g.student_id LEFT JOIN student s2 on g.student_id = s2.id </select> 这样,就完成了从数据库查询学生及其所拥有的成绩单,并将结果映射为Student的对象。其,每个Student对象的grades属性是一个List,其包含多个Grade的对象。 以上就是使用ResultMap实现MyBatis一对多映射的步骤。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值