Mybatis的集合查询
这次在自己练的项目中遇到了一个数据结构比较恶心的返回数据
[
{
className: "三年级一班",
students: [
{ name: "学生甲", id: "xxx" },
{ name: "学生乙", id: "xxx" },
{ name: "学生丙", id: "xxx" },
]
},
{
className: "三年级二班",
students: [
{ name: "学生甲", id: "xxx" },
{ name: "学生乙", id: "xxx" },
{ name: "学生丙", id: "xxx" },
]
}
]
这个返回的数据需要用到数据库表(其中user表中包括了学生跟老师的),如下:
user(userId,classId)
teacher_class(teacherId,classId)
classes(classId,gradeId,className)
grade(gradeId,gradeName)
一开始,我的思路就是先用老师Id获取对应的班级列表后,接着for循环进行班级列表的遍历,紧接着就是根据班级的Id获取班级中的学生。但是,如果这样意味着获取如果一个老师有多个班,获取一次这个老师所教的所有学生将多次访问数据库,这样将会建立多次数据库的链接,这将会浪费数据库资源。在初次尝试中,我就是这样做的,并且有一个sql判断写错,造成了一次500次的数据库连接,直接出现了too many connection的报错。
因此,在这里我将说说我最后解决上述问题,用的Mybatis集合查询的心得。
Mybatis集合查询适合于映射于StudentsDto这样的实体类
public class StudentsDto {
private String classId;
private String className;
private List<GetStudentDto> students;
public String getClassId() {
return classId;
}
public void setClassId(String classId) {
this.classId = classId;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public List<GetStudentDto> getStudents() {
return students;
}
public void setStudents(List<GetStudentDto> students) {
this.students = students;
}
}
其中的GetStudentDto类如下:
public class GetStudentDto {
private String name;
private String id;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
接着,就是配置mapper.xml文件
<resultMap id="StudentsDto" type="com.edu.dto.StudentsDto">
<result property="classId" column="classId" />
<result property="className" column="className" />
<collection property="students" javaType="ArrayList" column="getStudentDtos" ofType="com.edu.dto.GetStudentDto">
<result property="id" column="userid" />
<result property="name" column="username" />
</collection>
</resultMap>
<select id="getStudentsByTeacherId" resultMap="StudentsDto">
select
tcr.classId as classId,
concat(g.gradeName,c.className) as className,
u.userId as userid,
u.name as username
from
teacher_class_relationship tcr
join classes c on tcr.classId=c.classId
join grade g on c.gradeId=g.gradeId
join user u on u.classId=c.classId
where
teacherId=#{teacherId}
</select>
在resultMap标签中的id=”StudentsDto”就是一个标识,便于下面select标签引用,type的值就是整个resultMap的bean注入实体的对象位置。接下来的result标签就是普通字段,如果是主键字段就是id标签。在result与id标签中,有两个常用属性property和column。property就是对应实体中的字段名,column就是对应数据库字段名。
接下来就是collection标签,在collection标签中有几个常用属性,property字段值对应resultMap中引用实体的字段名,javaType就是对应的java数据类型,column就是指定的sql查询结果的字段名或字段别名,ofType就是collection的bean注入实体的对象位置。
按照这样写好后,就可以一次性的取到一开始讨论的返回数据
[
{
"className": "二年级二班",
"students": [
{
"name": "吴XX",
"id": "03b04eef-1c61-4b05-basc-7af95f6d26dc"
},
{
"name": "文XX",
"id": "1123553f-3fas-4b09-aabf-1ce331b8b5b4"
},
{
"name": "王XX",
"id": "12a3e6bd-7f45-4d56-bsde-2d4b922e1ab3"
}
]
},
{
"className": "一年级一班",
"students": [
{
"name": "刘XX",
"id": "1227929f-c83c-48fe-8db4-bd0as4e5d5f7"
},
{
"name": "沈XX",
"id": "1eb50dfa-3712-4150-92b3-9ba5sddd325"
},
{
"name": "李XX",
"id": "1fa73f79-2de0-4a0b-b478-46f2as098db"
}
]
}
]