业务需求,需要查询到的结果集如下
结构分析
1.查询出所有的评论,即data[]里面是一个list
2.查出list中每个评论id(即userObjectCmmtId)下面所有的子评论,即一对多的关系。
实现方法如下
1.接口层文件如下
2.实现层文件如下
3.返回第一层bean如下
返回第二层bean
4.xml文件如下(第一层)
<resultMap type="com.zhiji.caren.VO.CmmtRel" id="cmmtListMap"> <result column="USER_PERSON_CMMT_ID" property="userObjectCmmtId" jdbcType="VARCHAR" /> <result column="ROOT_USER_ID" property="rootUserId" jdbcType="INTEGER" /> <result column="ROOT_USER_IMG" property="rootUserImg" jdbcType="VARCHAR" /> <result column="ROOT_USER_NICKNAME" property="rootUserNickName" jdbcType="VARCHAR" /> <result column="ROOT_CMMT_CONTENT" property="rootCmmtContent" jdbcType="VARCHAR" /> <result column="ROOT_ADD_TIME" property="rootAddTime" jdbcType="VARCHAR" /> <collection property="cmmtData" javaType="ArrayList" column="{rootCmmtId = USER_PERSON_CMMT_ID" select="getSubCmmtInfo" /> </resultMap> <select id="selectCmmtList" resultMap="cmmtListMap"> SELECT tupctui.USER_PERSON_CMMT_ID, tupctui.ROOT_USER_ID, tupctui.ROOT_USER_IMG, tupctui.ROOT_USER_NICKNAME, tupctui.ROOT_CMMT_CONTENT, tupctui.ROOT_ADD_TIME from (SELECT tupc.USER_PERSON_CMMT_ID, tupc.USER_ID AS ROOT_USER_ID, tui.USER_IMG AS ROOT_USER_IMG, tui.NICKNAME AS ROOT_USER_NICKNAME, tupc.CMMT_CONTENT AS ROOT_CMMT_CONTENT, tupc.ADD_TIME AS ROOT_ADD_TIME FROM t_user_person_cmmt tupc,t_user_info tui WHERE tupc.USER_ID = tui.USER_ID AND tupc.ROOT_CMMT_ID is NULL AND PERSON_ID = #{objectId,jdbcType = INTEGER} <if test="lastTime != null"> AND tupc.ADD_TIME <= #{lastTime} </if> ORDER BY ROOT_ADD_TIME DESC) tupctui LIMIT #{pageIndex} </select>
xml文件第二层如下
<resultMap type="com.zhiji.caren.VO.CmmtRelChild" id="subCmmtMap"> <result column="SUPER_CMMT_ID" property="superCmmtId" jdbcType="VARCHAR" /> <result column="SUPER_USER_ID" property="superUserId" jdbcType="INTEGER" /> <result column="SUPER_NICKNAME" property="superNickName" jdbcType="VARCHAR" /> <result column="CHILD_USER_ID" property="childUserId" jdbcType="INTEGER" /> <result column="CHILD_USER_NICKNAME" property="childUserNickName" jdbcType="VARCHAR" /> <result column="CHILD_CMMT_CONTENT" property="childCmmtContent" jdbcType="VARCHAR" /> <result column="USER_PERSON_CMMT_ID" property="childCmmtId" jdbcType="VARCHAR" /> </resultMap> <select id="getSubCmmtInfo" resultMap="subCmmtMap"> SELECT tupc.ROOT_CMMT_ID, tupc.SUPER_CMMT_ID, tupc.SUPER_USER_ID, tuii.NICKNAME as SUPER_NICKNAME, tupc.USER_ID AS CHILD_USER_ID, tui.NICKNAME AS CHILD_USER_NICKNAME, tupc.CMMT_CONTENT AS CHILD_CMMT_CONTENT, tupc.USER_PERSON_CMMT_ID, tupc.ADD_TIME AS CHILD_ADD_TIME FROM t_user_person_cmmt tupc LEFT JOIN t_user_info tui on tupc.USER_ID = tui.USER_ID LEFT JOIN t_user_info tuii on tupc.SUPER_USER_ID = tuii.USER_ID WHERE tupc.ROOT_CMMT_ID IS NOT NULL AND ROOT_CMMT_ID = #{rootCmmtId} ORDER BY CHILD_ADD_TIME </select>
总结:如上例子中用到了mybatis的collection,即
<collection property="cmmtData" javaType="ArrayList" column="{rootCmmtId = USER_PERSON_CMMT_ID" select="getSubCmmtInfo" />
现在就这个点学习下写一篇文章
//参考文章如下链接,真心讲的不错,好东西拿出来大家分享
http://www.cnblogs.com/xdp-gacl/p/4264440.html
一、一对一关联查询
假设A表(班级表,t_class)
c_id c_name teacher_id
1 一班 x
2 二班 x
假设B表(教师表,t_teacher)
t_id t_name
1 张三
2 李四
现在业务需求:根据班级id查询班级信息(查询出该班级的老师信息,假设班级与教师一对一关系)
方法一:嵌套结果--联表查询,一次查询得出结果
<!-- 使用resultMap映射实体类和字段之间的一一对应关系 --> <resultMap type="me.gacl.domain.Classes" id="ClassResultMap"> <id property="id" column="c_id"/> <result property="name" column="c_name"/> <association property="teacher" javaType="me.gacl.domain.Teacher"> <id property="id" column="t_id"/> <result property="name" column="t_name"/> </association> </resultMap> <select id="getClass" parameterType="int" resultMap="ClassResultMap"> select * from class c, teacher t where c.teacher_id=t.t_id and c.c_id=#{id} </select>
备注:实际过程中,我可能不会用到association那段,我在 me.gacl.domain.classes中定义属性的时候,直接将班级属性和老师属性定义在一起,这样resultMap就可以改写成如下
<resultMap type="me.gacl.domain.ClassesAndTeacher" id="ClassResultMap"> <id property="cid" column="c_id"/> <result property="name" column="c_name"/> <result property="tid" column="t_id"/> <result property="name" column="t_name"/> </resultMap>
最后,仔细考虑下,还是觉得分开要好些,因为班级bean和教师bean是两个基础bean,而我根据这个业务需求还需要重新定义一个混合bean,即浪费了一个bean。按理推之,如果每个业务都需要关联多张表,按照我的做法,即需要新建多个bean,按照第一种方法,则只需要关联基础bean就行。
方法二:嵌套查询--多次查询得出结果
<select id="getClass2" parameterType="int" resultMap="ClassResultMap"> select * from class where c_id=#{id} </select> <resultMap type="me.gacl.domain.Classes" id="ClassResultMap"> <id property="id" column="c_id"/> <result property="name" column="c_name"/> <association property="teacher" column="teacher_id" select="getTeacher"/> </resultMap> <select id="getTeacher" parameterType="int" resultType="me.gacl.domain.Teacher"> SELECT t_id id, t_name name FROM teacher WHERE t_id=#{id} </select>
备注:很明显这是分两次查询,先用#{id}查询班级信息,再用#{id}查询教师信息。
总结:
MyBatis中使用association标签来解决一对一的关联查询,association标签可用的属性如下:
property:对象属性的名称
javaType:对象属性的类型
column:所对应的外键字段名称
select:使用另一个查询封装的结果
二、一对多关联查询
新的需求:根据班级id查询出班级信息(包括教师,学生)。班级与教师一对一关系,班级与学生一对多关系。
现在需要在如上数据库表的基础上加上学生表
假设C表(学生表,t_student)
s_id s_name s_classId
1 小吴 x
2 小李 x
1.返回的结构如下
public class classInfo { //班级id private int id; //班级名称 private String name; /** * class表中有一个teacher_id字段,所以在Classes类中定义一个teacher属性, * 用于维护teacher和class之间的一对一关系,通过这个teacher属性就可以知道这个班级是由哪个老师负责的 **/ private Teacher teacher; //使用一个List<Student>集合属性表示班级拥有的学生 private List<Student> students; }
方法一:嵌套结果--联表查询,一次查询得出结果
<resultMap type="me.gacl.domain.Classes" id="ClassResultMap"> <id property="id" column="c_id"/> <result property="name" column="c_name"/> <association property="teacher" column="teacher_id" javaType="me.gacl.domain.Teacher"> <id property="id" column="t_id"/> <result property="name" column="t_name"/> </association> <!-- ofType指定students集合中的对象类型 --> <collection property="students" ofType="me.gacl.domain.Student"> <id property="id" column="s_id"/> <result property="name" column="s_name"/> </collection> </resultMap> <select id="getClass" parameterType="int" resultMap="ClassResultMap"> select * from class c, teacher t,student s where c.teacher_id=t.t_id and c.C_id=s.class_id and c.c_id=#{id} </select>
方法二:嵌套查询
<select id="getClass" parameterType="int" resultMap="ClassResultMap"> select * from class where c_id=#{id} </select> <resultMap type="me.gacl.domain.Classes" id="ClassResultMap"> <id property="id" column="c_id"/> <result property="name" column="c_name"/> <association property="teacher" column="teacher_id" javaType="me.gacl.domain.Teacher" select="getTeacher"> </association> <collection property="students" ofType="me.gacl.domain.Student" column="c_id" select="getStudent"> </collection> </resultMap> <select id="getTeacher" parameterType="int" resultType="me.gacl.domain.Teacher"> SELECT t_id id, t_name name FROM teacher WHERE t_id=#{id} </select> <select id="getStudent" parameterType="int" resultType="me.gacl.domain.Student"> SELECT s_id id, s_name name FROM student WHERE class_id=#{id} </select>
备注:
select * from class where c_id=#{id} //#{id}是是实现层传过来的值
select t_id,t_name from teacher where t_id=#{id} //#{id}是上一个查询得到的teacher_id
select s_id,s_name from student where s_classId=#{id} //#{id}是查询到的c_id
总结:MyBatis中使用collection标签来解决一对多的关联查询,ofType属性指定集合中元素的对象类型。