当前位置:   article > 正文

MyBatis入门(六)关联查询_mybatis 关联查询

mybatis 关联查询

目录

一.关联查询

二.一对一关联查询

三.一对多关联查询

四.多对多关联查询


一.关联查询

MyBatis 的关联查询分为一对一关联查询和一对多关联查询。
  • 查询对象时,将关联的另一个对象查询出来,就是一对一关联查询。
  • 查询对象时,将关联的另一个对象的集合查询出来,就是一对多关联查询。
例如有学生类和班级类:
一个学生对应一个班级,也就是学生类中有一个班级属性,这就是一对一关系。
一个班级对应多个学生,也就是班级类中有一个学生集合属性,这就是一对多关系。
新建一个子工程:
右键父工程,New-->Module

并把mybatisDemo1中的pom.xml的依赖配置代码复制到 mybatisDemo2中

将mybatisDemo1中的resources的如下三个文件复制到mybatisDemo2中的resources下

 并且将核心配置文件SqlMapConfig.xml中不需要的东西去掉,去完之后如下:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE configuration
  3. PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-config.dtd">
  5. <configuration>
  6. <properties resource="db.properties"></properties>
  7. <!--配置环境-->
  8. <environments default="mysql">
  9. <environment id="mysql">
  10. <transactionManager type="JDBC"></transactionManager>
  11. <dataSource type="POOLED">
  12. <property name="driver" value="${jdbc.driver}"/>
  13. <property name="url" value="${jdbc.url}"/>
  14. <property name="username" value="${jdbc.username}"/>
  15. <property name="password" value="${jdbc.password}"/>
  16. </dataSource>
  17. </environment>
  18. </environments>
  19. <!-- 注册映射文件-->
  20. <mappers>
  21. <mapper resource="com/first/mapper/StudentMapper.xml"></mapper>
  22. </mappers>
  23. </configuration>
实体类设计如下:

 在java包下创建com/first/pojo

在pojo下创建Classes类和Student类

Student.java:

  1. package com.first.pojo;
  2. public class Student {
  3. private int sid;
  4. private String name;
  5. private int age;
  6. private String sex;
  7. private Classes classes;
  8. public int getSid() {
  9. return sid;
  10. }
  11. public void setSid(int sid) {
  12. this.sid = sid;
  13. }
  14. public String getName() {
  15. return name;
  16. }
  17. public void setName(String name) {
  18. this.name = name;
  19. }
  20. public int getAge() {
  21. return age;
  22. }
  23. public void setAge(int age) {
  24. this.age = age;
  25. }
  26. public String getSex() {
  27. return sex;
  28. }
  29. public void setSex(String sex) {
  30. this.sex = sex;
  31. }
  32. public Classes getClasses() {
  33. return classes;
  34. }
  35. public void setClasses(Classes classes) {
  36. this.classes = classes;
  37. }
  38. @Override
  39. public String toString() {
  40. return "Student{" +
  41. "sid=" + sid +
  42. ", name='" + name + '\'' +
  43. ", age=" + age +
  44. ", sex='" + sex + '\'' +
  45. ", classes=" + classes +
  46. '}';
  47. }
  48. }

Classes.java:

  1. package com.first.pojo;
  2. import java.util.List;
  3. public class Classes {
  4. private int cid;
  5. private String className;
  6. private List<Student> studentList;
  7. public int getCid() {
  8. return cid;
  9. }
  10. public void setCid(int cid) {
  11. this.cid = cid;
  12. }
  13. public String getClassName() {
  14. return className;
  15. }
  16. public void setClassName(String className) {
  17. this.className = className;
  18. }
  19. public List<Student> getStudentList() {
  20. return studentList;
  21. }
  22. public void setStudentList(List<Student> studentList) {
  23. this.studentList = studentList;
  24. }
  25. @Override
  26. public String toString() {
  27. return "Classes{" +
  28. "cid=" + cid +
  29. ", className='" + className + '\'' +
  30. ", studentList=" + studentList +
  31. '}';
  32. }
  33. }

 数据库设计如下:

二.一对一关联查询

查询学生时,将关联的一个班级对象查询出来,就是一对一关联查询。
创建持久层接口

 在com/first/mapper下创建接口文件StudentMapper.java

  1. package com.first.mapper;
  2. import com.first.pojo.Student;
  3. import java.util.List;
  4. public interface StudentMapper {
  5. List<Student> findAll();
  6. }
创建映射文件
再resources下创建com,再在com下创建first,再在first创建mapper(注意要一步一步来),
然后在mapper下创建映射文件StudentMapper.xml
先看一下数据库中的列名:
而且在创建Classes类和Student类时普通类属性也是根据数据库的表的列名创建的。

那么现在我们再来看如下利用resultMap自定义的映射关系:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <!--映射文件-->
  6. <!--namespace设置映射的文件-->
  7. <mapper namespace="com.first.mapper.StudentMapper">
  8. <!-- id:自定义映射名 type:自定义映射的对象类型-->
  9. <resultMap id="studentMapper" type="com.first.pojo.Student">
  10. <!-- id定义主键列 property:POJO属性名 column:数据库列名 -->
  11. <id property="sid" column="sid"></id>
  12. <!-- result定义普通列 property:POJO属性名 column:数据库列名 -->
  13. <result property="name" column="name"></result>
  14. <result property="age" column="age"></result>
  15. <result property="sex" column="sex"></result>
  16. <!--对象的话就用association,列表就用collection -->
  17. <!--一对一对象列,property:属性名,column:关联类名(这里classId或cid都行),javaType:对象类型-->
  18. <association property="classes" column="classId" javaType="com.first.pojo.Classes">
  19. <!--关联对象主键列-->
  20. <id property="cid" column="cid"></id>
  21. <!--关联对象普通列-->
  22. <result property="className" column="className"></result>
  23. </association>
  24. </resultMap>
  25. <select id="findAll" resultMap="studentMapper">
  26. select * from student left join classes on student.classId = classes.cid;
  27. </select>
  28. </mapper>
测试类:
TestManyTablesQuery.java:
  1. import com.first.mapper.StudentMapper;
  2. import com.first.pojo.Student;
  3. import org.apache.ibatis.io.Resources;
  4. import org.apache.ibatis.session.SqlSession;
  5. import org.apache.ibatis.session.SqlSessionFactory;
  6. import org.apache.ibatis.session.SqlSessionFactoryBuilder;
  7. import org.junit.After;
  8. import org.junit.Before;
  9. import org.junit.Test;
  10. import java.io.IOException;
  11. import java.io.InputStream;
  12. import java.util.List;
  13. public class TestManyTablesQuery {
  14. //全局变量
  15. InputStream is=null;
  16. SqlSession session =null;
  17. //前置方法:测试类里的测试方法执行之前都会先执行前置方法
  18. @Before
  19. public void before() throws IOException {
  20. //(1)读取核心配置文件
  21. is= Resources.getResourceAsStream("SqlMapConfig.xml");
  22. //(2)创建SqlSessionFactoryBuilder对象
  23. SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
  24. //(3)SqlSessionFactoryBuilder对象获取SqlSessionFactory对象
  25. SqlSessionFactory factory = builder.build(is);
  26. //(4)SqlSessionFactory对象获取SqlSession对象
  27. session = factory.openSession();
  28. }
  29. //后置方法:测试类里的测试方法执行之后都会执行后置方法
  30. @After
  31. public void after() throws IOException {
  32. //(7)释放资源
  33. session.close();
  34. is.close();
  35. }
  36. @Test
  37. public void testFindAll(){
  38. StudentMapper studentMapper = session.getMapper(StudentMapper.class);
  39. List<Student> all = studentMapper.findAll();
  40. all.forEach(System.out::println);
  41. }
  42. }

输出:

  1. Student{sid=1, name='张三', age=10, sex='男', classes=Classes{cid=1, className='三年一班', studentList=null}}
  2. Student{sid=2, name='李四', age=10, sex='女', classes=Classes{cid=1, className='三年一班', studentList=null}}
  3. Student{sid=3, name='尚尚', age=10, sex='男', classes=Classes{cid=2, className='三年二班', studentList=null}}
  4. Student{sid=4, name='百战', age=11, sex='男', classes=Classes{cid=2, className='三年二班', studentList=null}}
  5. Student{sid=5, name='王五', age=10, sex='男', classes=Classes{cid=2, className='三年二班', studentList=null}}

三.一对多关联查询

查询班级时,将关联的学生集合查询出来,就是一对多关联查询。

创建持久层接口

  1. package com.first.mapper;
  2. import com.first.pojo.Classes;
  3. import java.util.List;
  4. public interface ClassesMapper {
  5. List<Classes> findAll();
  6. }

 创建映射文件ClassesMapper.xml:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <!--映射文件-->
  6. <!--namespace设置映射的文件-->
  7. <mapper namespace="com.first.mapper.ClassesMapper">
  8. <!-- id:自定义映射名 type:自定义映射的对象类型-->
  9. <resultMap id="classesMapper" type="com.first.pojo.Classes">
  10. <!-- id定义主键列 property:POJO属性名 column:数据库列名 -->
  11. <id property="cid" column="cid"></id>
  12. <!-- result定义普通列 property:POJO属性名 column:数据库列名 -->
  13. <result property="className" column="className"></result>
  14. <!--一对多集合列,property:属性名,column:关联类名(这里classId和cid),ofType:集合的泛型类型-->
  15. <!--List也属于集合的一种-->
  16. <collection property="studentList" column="classId" ofType="com.first.pojo.Student">
  17. <id property="sid" column="sid"></id>
  18. <result property="name" column="name"></result>
  19. <result property="age" column="age"></result>
  20. <result property="sex" column="sex"></result>
  21. </collection>
  22. </resultMap>
  23. <select id="findAll" resultMap="classesMapper">
  24. select * from classes left join student on student.classId = classes.cid;
  25. </select>
  26. </mapper>

注册映射文件:

测试一对多关联查询

  1. @Test
  2. public void testFindAllClasses(){
  3. ClassesMapper classesMapper = session.getMapper(ClassesMapper.class);
  4. List<Classes> all = classesMapper.findAll();
  5. all.forEach(System.out::println);
  6. }

输出:

  1. Classes{cid=1, className='三年一班', studentList=[Student{sid=1, name='张三', age=10, sex='男', classes=null}, Student{sid=2, name='李四', age=10, sex='女', classes=null}]}
  2. Classes{cid=2, className='三年二班', studentList=[Student{sid=3, name='尚尚', age=10, sex='男', classes=null}, Student{sid=4, name='百战', age=11, sex='男', classes=null}, Student{sid=5, name='王五', age=10, sex='男', classes=null}]}

四.多对多关联查询

MyBatis 多对多关联查询本质就是两个一对多关联查询。
例如有老师类和班级类:
一个老师对应多个班级,也就是老师类中有一个班级集合属性。
一个班级对应多个老师,也就是班级类中有一个老师集合属性。
实体类设计如下:
Teacher类:
  1. package com.first.pojo;
  2. import java.util.List;
  3. public class Teacher {
  4. private int tid;
  5. private String tname;
  6. private List<Classes> classes;
  7. public int getTid() {
  8. return tid;
  9. }
  10. public void setTid(int tid) {
  11. this.tid = tid;
  12. }
  13. public String getTname() {
  14. return tname;
  15. }
  16. public void setTname(String tname) {
  17. this.tname = tname;
  18. }
  19. public List<Classes> getClasses() {
  20. return classes;
  21. }
  22. public void setClasses(List<Classes> classes) {
  23. this.classes = classes;
  24. }
  25. @Override
  26. public String toString() {
  27. return "Teacher{" +
  28. "tid=" + tid +
  29. ", tname='" + tname + '\'' +
  30. ", classes=" + classes +
  31. '}';
  32. }
  33. }

Classes类:

  1. package com.first.pojo;
  2. import java.util.List;
  3. public class Classes {
  4. private int cid;
  5. private String className;
  6. private List<Student> studentList;
  7. private List<Teacher> teacherList;
  8. public int getCid() {
  9. return cid;
  10. }
  11. public void setCid(int cid) {
  12. this.cid = cid;
  13. }
  14. public String getClassName() {
  15. return className;
  16. }
  17. public void setClassName(String className) {
  18. this.className = className;
  19. }
  20. public List<Student> getStudentList() {
  21. return studentList;
  22. }
  23. public void setStudentList(List<Student> studentList) {
  24. this.studentList = studentList;
  25. }
  26. public List<Teacher> getTeacherList() {
  27. return teacherList;
  28. }
  29. public void setTeacherList(List<Teacher> teacherList) {
  30. this.teacherList = teacherList;
  31. }
  32. @Override
  33. public String toString() {
  34. return "Classes{" +
  35. "cid=" + cid +
  36. ", className='" + className + '\'' +
  37. ", studentList=" + studentList +
  38. ", teacherList=" + teacherList +
  39. '}';
  40. }
  41. }
在数据库设计中,需要建立中间表,双方与中间表均为一对多关系。

因为老师类和班级类没有公共字段,所以需要借助于一个中间表来将两个表连起来。

接下来测试查询老师时,将关联的班级集合查询出来。
创建持久层接口
  1. package com.first.mapper;
  2. import com.first.pojo.Teacher;
  3. import java.util.List;
  4. public interface TeacherMapper {
  5. List<Teacher> findAll();
  6. }
创建映射文件TeacherMapper.xml:
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <!--映射文件-->
  6. <!--namespace设置映射的文件-->
  7. <mapper namespace="com.first.mapper.TeacherMapper">
  8. <!-- id:自定义映射名 type:自定义映射的对象类型-->
  9. <resultMap id="teacherMapper" type="com.first.pojo.Teacher">
  10. <!-- id定义主键列 property:POJO属性名 column:数据库列名 -->
  11. <id property="tid" column="tid"></id>
  12. <!-- result定义普通列 property:POJO属性名 column:数据库列名 -->
  13. <result property="tname" column="tname"></result>
  14. <!--对象的话就用association,列表就用collection -->
  15. <!--集合列,property:属性名,column:关联类名(这里classId或cid都行),javaType:对象类型-->
  16. <collection property="classes" column="tid" ofType="com.first.pojo.Classes">
  17. <!--关联对象主键列-->
  18. <id property="cid" column="cid"></id>
  19. <!--关联对象普通列-->
  20. <result property="className" column="className"></result>
  21. </collection>
  22. </resultMap>
  23. <select id="findAll" resultMap="teacherMapper">
  24. select * from teacher
  25. left join classes_teacher
  26. on teacher.tid = classes_teacher.tid
  27. left join classes
  28. on classes_teacher.cid = classes.cid
  29. </select>
  30. </mapper>

在核心配置文件中注册映射文件:

测试多对多关联查询

  1. @Test
  2. public void testFindAllTeacher(){
  3. TeacherMapper teacherMapper = session.getMapper(TeacherMapper.class);
  4. List<Teacher> all = teacherMapper.findAll();
  5. all.forEach(System.out::println);
  6. }

输出:

  1. Teacher{tid=1, tname='王老师', classes=[Classes{cid=1, className='三年一班', studentList=null, teacherList=null}]}
  2. Teacher{tid=2, tname='李老师', classes=[Classes{cid=1, className='三年一班', studentList=null, teacherList=null}, Classes{cid=2, className='三年二班', studentList=null, teacherList=null}]}
  3. Teacher{tid=3, tname='张老师', classes=[Classes{cid=2, className='三年二班', studentList=null, teacherList=null}]}

接下来测试查询班级时,将关联的老师集合查询出来。

对ClassesMapper.xml进行修改

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <!--映射文件-->
  6. <!--namespace设置映射的文件-->
  7. <mapper namespace="com.first.mapper.ClassesMapper">
  8. <!-- id:自定义映射名 type:自定义映射的对象类型-->
  9. <resultMap id="classesMapper" type="com.first.pojo.Classes">
  10. <!-- id定义主键列 property:POJO属性名 column:数据库列名 -->
  11. <id property="cid" column="cid"></id>
  12. <!-- result定义普通列 property:POJO属性名 column:数据库列名 -->
  13. <result property="className" column="className"></result>
  14. <!--一对多集合列,property:属性名,column:关联类名(这里classId和cid),ofType:集合的泛型类型-->
  15. <!--List也属于集合的一种-->
  16. <!--学生集合-->
  17. <collection property="studentList" column="classId" ofType="com.first.pojo.Student">
  18. <id property="sid" column="sid"></id>
  19. <result property="name" column="name"></result>
  20. <result property="age" column="age"></result>
  21. <result property="sex" column="sex"></result>
  22. </collection>
  23. <!--老师集合-->
  24. <collection property="teacherList" column="cid" ofType="com.first.pojo.Teacher">
  25. <!--关联对象主键列-->
  26. <id property="tid" column="tid"></id>
  27. <!--关联对象普通列-->
  28. <result property="tname" column="tname"></result>
  29. </collection>
  30. </resultMap>
  31. <select id="findAll" resultMap="classesMapper">
  32. select * from classes
  33. left join student
  34. on student.classId = classes.cid
  35. left join classes_teacher
  36. on classes.cid=classes_teacher.cid
  37. left join teacher
  38. on classes_teacher.tid=teacher.tid;
  39. </select>
  40. </mapper>

 测试函数就用之前写的testFindAllClasses():

  1. @Test
  2. public void testFindAllClasses(){
  3. ClassesMapper classesMapper = session.getMapper(ClassesMapper.class);
  4. List<Classes> all = classesMapper.findAll();
  5. all.forEach(System.out::println);
  6. }

输出:

  1. Classes{cid=1, className='三年一班', studentList=[Student{sid=1, name='张三', age=10, sex='男', classes=null}, Student{sid=2, name='李四', age=10, sex='女', classes=null}], teacherList=[Teacher{tid=1, tname='王老师', classes=null}, Teacher{tid=2, tname='李老师', classes=null}]}
  2. Classes{cid=2, className='三年二班', studentList=[Student{sid=3, name='尚尚', age=10, sex='男', classes=null}, Student{sid=4, name='百战', age=11, sex='男', classes=null}, Student{sid=5, name='王五', age=10, sex='男', classes=null}], teacherList=[Teacher{tid=2, tname='李老师', classes=null}, Teacher{tid=3, tname='张老师', classes=null}]}

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/168771
推荐阅读
相关标签
  

闽ICP备14008679号