MyBatis多对一、多对一处理

在人生的道路上,不管是潇洒走一回,或者是千山独行,皆须是自己想走的路,虽然,有的人并不是很快就能找到自己的方向和道路,不过,只要坚持到底,我相信,就一定可以找到自己的路,只要找到路,就不必怕路途遥远了。

导读:本篇文章讲解 MyBatis多对一、多对一处理,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

10.多对一、多对一处理

  • 一个班级有多个学生
  • 学生角度:(关联)多个学生关联一个班级
  • 班级角度:(集合)一个班级集合了多个学生

10.1 环境搭建

  • 数据库建表
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, '王老师'); 

CREATE TABLE `students` (
  `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=utf8INSERT INTO `students` (`id`, `name`, `tid`) VALUES ('1', '小明', '1'); 
INSERT INTO `students` (`id`, `name`, `tid`) VALUES ('2', '小红', '1'); 
INSERT INTO `students` (`id`, `name`, `tid`) VALUES ('3', '小张', '1'); 
INSERT INTO `students` (`id`, `name`, `tid`) VALUES ('4', '小李', '1'); 
INSERT INTO `students` (`id`, `name`, `tid`) VALUES ('5', '小王', '1');
  • 建实体类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Teacher {
    private int id;
    private String name;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Students {
    private  int id;
    private   String   name;
    //多个学生对应一个老师
    private Teacher teacher;
}
  • 建Mapper接口和mapper.xml
  • 可以将mapper.xml放到项目的resources下同包目录下,dao包中只保留Mapper接口,编译后同包目录下的文件都输出到target文件中
  • 在核心配置文件中注册mapper接口
  • 测试查询是否成功

10.2 多对一实现方式

  • 按照查询进行嵌套处理:子查询
  • 题目:查询所有的学生消息(附带老师信息)
<?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.zk.dao.StudentsMapper">
    <!--包扫描的别名方式,返回值、映射对象类型的首字母大小写无关-->
    <resultMap id="StudentsTeacher" type="students">
        <result property="id" column="id"></result>
        <!--复杂属性单独处理
            对象使用association
            集合使用collection
        -->
        <!--按照查询进行嵌套处理,子查询
        column="tid"是作为子查询参数来映射的,但字段来自已经查处来的students对象-->
        <association property="teacher" column="tid" javaType="teacher" select="getTeacherByTID">
        </association>
    </resultMap>
    <select id="getStudents" resultMap="StudentsTeacher">
        select * from students ;
    </select>
    <select id="getTeacherByTID" resultType="teacher">
        select * from teacher where id = #{tid};
    </select>
</mapper>
  • 按照结果进行嵌套处理:关联查询
<select id="getStudents2" resultMap="StudentsTeacher2">
    SELECT s.id sid,s.name sname ,t.id tid,t.name tname FROM students s,teacher t WHERE s.tid = t.id
</select>
<resultMap id="StudentsTeacher2" type="students">
    <result property="id" column="sid"/>
    <result property="name" column="sname"/>
    <association property="teacher"  javaType="teacher">
        <result property="id" column="tid"/>
        <result property="name" column="tname"/>
    </association>
</resultMap>

10.3 一对多实现方式

  • 题目:查询一个老师代课的学生消息

  • 实体类修改

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Students {
    private  int id;
    private   String   name;
    private int tid;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Teacher {
    private int id;
    private String name;
    //一个老师关联多个学生
    private List<Students> students;
}
  • 按查询进行嵌套处理,子查询方式
 <!--子查询-->
    <select id="getTeacherListByIds02" resultMap="TeacherStudents02">
        select * from teacher where id = #{id}
    </select>
    <resultMap id="TeacherStudents02" type="Teacher">
        <result property="id" column="id"/>
        <!--为什么要加javaType的原因:
         1.上下面的是联表查询,两个表联合的一个个记录查出来,每条记录包含老师学生信息,
         2.这个是先查出来了要查询的老师id后,得到了查询结果,但结果中的的student是null值,
         所以要拿老师id进行对Students表子查询,子查询中结果是多条只有学生学习的记录。这些记录组成list
         形成resultMap-->
        <!--column="id"是作为子查询参数来映射的,但字段来自已经查处来的Teacher对象-->
        <collection property="students" column="id" javaType="ArrayList" ofType="Students" select="getTeacherByID"/>
    </resultMap>
    <select id="getTeacherByID" resultType="Students">
        select * from students where tid = #{id}
    </select>
  • 按结果进行嵌套处理,关联查询
<mapper namespace="com.zk.dao.TeacherMapper">

    <!--按照结果进行嵌套处理:关联查询-->
<select id="getTeacherListByIds" resultMap="TeacherStudents" >
  SELECT s.id sid,s.name sname ,t.id tid,t.name tname FROM students s,teacher t WHERE s.tid = t.id
    and t.id = #{id}
</select>

    <resultMap id="TeacherStudents" type="Teacher">
        <result property="id" column="tid"/>
        <result property="name" column="tname"/>
        <!--复杂属性单独处理
           对象使用associatiogetTeacherListByIdsn
           集合使用collection
           javaType="";指定属性的类型
           ofType="";集合中的泛型属性
           从集合中取出的-数据-来对应
       -->
        <collection property="students" ofType="Students">
            <result property="id" column="sid"/>
            <result property="name" column="sname"/>
        </collection>
    </resultMap>
  
</mapper>
  • 测试
@Test
public void test03(){
    SqlSession sqlSession = MybatisUtil.getSqlSession();
    TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);
    Teacher teacher = mapper.getTeacherListByIds02(1);
    System.out.println(teacher.toString());
    sqlSession.close();
    /*Teacher(id=1, name=王老师,
    students=[Students(id=1, name=小明, tid=0),
    Students(id=2, name=小红, tid=0), Students(id=3, name=小张, tid=0),
     Students(id=4, name=小李, tid=0),  Students(id=5, name=小王, tid=0)])
     */
}
  • 小结

collection:一对多

association:多对一

javaType=“”;指定实体类中属性的类型
ofType=“”;指定映射到集合中的实体类型,集合中的泛型属性

  • 注意

sql的可读性

一对多和多对一,属性和字段的映射关系

可以使用日志来排错

本专栏下一篇:MyBatis动态sql

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/123918.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!