Mybatis级联查询
一、环境说明
学生表(com_student)和学生档案表(com_archives)的关系是一对一,即一名学生只有一个档案,一个档案只能代表一名学生。 学生表(com_student)和学生班级表(com_class)的关系是一对多,即一名学生只有一个班级,一个班级有众多学生。 学生表(com_student)和学生课程表(com_course)的关系是多对多,即一名学生有多门课程,一门课程有多名学生选修。
二、一对一
1.association级联属性查询
说明:档案类(Archives.java)是学生类(Student.java)的一个属性;查询结束返回的是一个对象。 使用场景:查询出某一个学生的所有信息并且显示出该学生的档案信息。
Student实体
javapublic class Student { private int id; private String stuName; private int stuAge; //课程表的外键 private int stuClassId; }Archives实体
javapublic class Archives { private int id; private String archName; private String archNum; //学生表的外键 private int stuId; }StudentDao.xml
xml<select id="getStudent" resultMap="getStudentForAssoc"> select stu.*, arch.id aid, arch.arch_name, arch.arch_num, arch.stu_id from com_student stu left join com_archives arch on stu.id = arch.stu_id where stu.id=#{id} </select> <!-- 方法一:了解 --> <resultMap type="com.xx.Bean.Student" id="getStudentForSimple"> <id property="id" column="id"/> <result property="stuName" column="stu_name"/> <result property="stuAge" column="stu_age"/> <result property="stuClassId" column="stu_class_id"/> <result property="arch.id" column="aid"/> <result property="arch.archName" column="arch_name"/> <result property="arch.archNum" column="arch_num"/> <result property="arch.stuId" column="stu_id"/> </resultMap> <!-- 方法二:使用此种方法!!! --> <resultMap type="com.xx.Bean.Student" id="getStudentForAssoc"> <!-- property:类的属性, column:查询出来的字段名。 通过resultMap将MyBaits查询出来的数据和实体类的字段名一一对应。 --> <id property="id" column="id"/> <result property="stuName" column="stu_name"/> <result property="stuAge" column="stu_age"/> <result property="stuClassId" column="stu_class_id"/> <!-- association表示将两个对象联合起来,使MyBatis能够知道谁是谁的对象,谁该怎样封装谁!!! property:表示实体类(Student)下边的哪一个属性。 javaType:表示实体类(Student)下边的arch属性要封装com.xx.Bean.Archives类。 --> <association property="arch" javaType="com.xx.Bean.Archives"> <result property="id" column="aid"/> <result property="archName" column="arch_name"/> <result property="archNum" column="arch_num"/> <result property="stuId" column="stu_id"/> </association> </resultMap>说明
执行顺序:
- MyBatis首先执行select语句,从数据库中查询
- 然后MyBatis准备返回数据,默认是按照resultType返回;但是此处找到了resultMap自定义的规则,于是对照resultMap中的唯一标志getStudentForAssoc名去找对应的规则。
- 找到对应resultMap规则后,按照规则提示一个对一个的封装!!!
- 总结:自定义规则的时候,只需记住property代表要封装的实体类属性,column代表数据库中已经查出来的数据字段,我们要将数据字段封装进实体类属性当中!
2.association分步查询
使用场景同“集合查询”一样,不同的是,使用集合级联查询的方式书写sql语句比较复杂。分步查询符合个人所能想到的最简单的思维逻辑; 即:我先按照id查询出这个学生的详细来,然后在学生的详细信息中找到该学生的档案编号,再根据这个档案表好去查询学生的详细档案信息。
StudentDao.java(学生接口类)
java//新加分步查询方法 public Student spiltGetStudent(int id);ArchivesDao.java(档案接口类)
java//按照id查询档案信息 //首先执行的是查询学生信息的mapper映射语句,然后想办法将查询出来的id传递到此处。 public Archives getArchivesByid(int id);ArchivesDao.xml(按照id查询档案)
xml<mapper namespace="com.xx.Dao.ArchivesDao"> <!-- 查询档案,返回的是一个档案实体类 --> <select id="getArchivesByid" resultType="com.xx.Bean.Archives"> select * from com_archives where id=#{id} </select>StudentDao.xml(按照id查询学生)
xml<!-- 按照id查询出学生信息,然后执行自定义的resultMap规则 --> <select id="spiltGetStudent" resultMap="spiltGetStudentForAssc"> select * from com_student where id=#{id} </select> <!-- --> <resultMap type="com.xx.Bean.Student" id="spiltGetStudentForAssc"> <id property="id" column="id"/> <result property="stuName" column="stu_name"/> <result property="stuAge" column="stu_age"/> <result property="stuClassId" column="stu_class_id"/> <!-- 逻辑:我查询出学生的信息了,接下来应该告诉mybais怎样根据当前信息去查询档案数据库。 select:指定一个查询sql的唯一标识(就是告诉MyBatis接下来去使用select指定的这个查询),其余的封装操作由MyBatis完成。 column:要传入的条件(此处是id,和select指定的查询语句对应)。 注意:select尽量对应全类名。 --> <association property="arch" select="com.xx.Dao.ArchivesDao.getArchivesByid" column="id"> </association> </resultMap>
三、一对多
1.集合查询
说明:班级类(Class.java)中有一个是学生类(Student.java)的列表属性,保存了这个班级中的所有学生,查询结束返回的是一个集合。 使用场景:查询某一个班级的具体信息并且返回该班级下的所有学生信息。
Class.java(实体类)
javapublic class Class { private int id; private String className; private String classNum; //列表属性,用来保存本班级下面的所有的学生。 private List<Student> students; }ClassDao.java(接口)
java//传入班级的id,返回本班级的基本信息以及本班级下面的所有的学生的信息->collection public List<Class> getClassStudent(int id); //传入班级的id,返回本班级的基本信息以及本班级下面的所有的学生的信息->分步查询。 public List<Class> splitGetClassStudent(int id);ClasstDao.xml(映射配置文件)
xml<!-- 先去数据库中执行,成功执行之后再去写resultMap --> <select id="getClassStudent" resultMap="classStudents"> select c.*, stu.id sid, stu.stu_name, stu.stu_age, stu.stu_class_id from com_class c left join com_student stu on c.id = stu.stu_class_id where c.id=#{id}; </select> <!-- type是对班级类定义的封装规则,该规则的唯一标识是classStudents --> <resultMap type="com.xx.Bean.Class" id="classStudents"> <!-- collection:定义集合元素的封装 property:指定实体类的哪一个属性是集合属性,MyBatis会将查询出来的集合封装到这里。 javaType:指定对象的类型,和ofType区分。 ofType:指定集合里面元素的类型。 --> <id property="id" column="id"/> <result property="className" column="class_name"/> <result property="classNum" column="class_num"/> <collection property="students" ofType="com.xx.Bean.Student"> <result property="id" column="sid"/> <result property="stuName" column="stu_name"/> <result property="stuAge" column="stu_age"/> <result property="stuClassId" column="stu_class_id"/> </collection> </resultMap>
2.collection分步查询
ClassDao.java
javapublic List<Class> splitGetClassStudent(int id);StudentDao.java
java//使用collection的分步查询 //根据传递过来的班级ID查询出该班级所有的学生信息 public List<Student> getStudentListByClassId(int id);StudentDao.xml
xml<select id="splitGetClassStudent" resultMap="splitGetClassStudentMap"> select * from com_class where id=#{id} </select> <resultMap type="com.xx.Bean.Class" id="splitGetClassStudentMap"> <id property="id" column="id"/> <result property="className" column="class_name"/> <result property="classNum" column="class_num"/> <collection property="students" select="com.xx.Dao.StudentDao.getStudentListByClassId" column="id"> </collection> </resultMap>StudentDao.xml
xml<!-- resultType是集合里面元素的类型 --> <!-- 根据传递过来的班级ID查询出该班级所有的学生信息 --> <select id="getStudentListByClassId" resultType="com.xx.Bean.Student"> select * from com_student where stu_class_id=#{id} </select>