mybatis中,可以使用collection和association来处理一对多和多对一的关系
其中每个标签中有2中种使用方式,一种是嵌套查询,一种是嵌套结果
嵌套查询会在主查询中,去调用子查询
嵌套结果只需要查询一次,将结果进行封装
一、前提准备
1、数据库表
创建2张表,class和student,class和student是一对多
2张表的数据如下:
class:
student:
2、创建2个实体类对象
TClass
@Data
public class TClass extends Model<TClass> {
private static final long serialVersionUID = 1L;
private String id;
private String name;
private String code;
@TableField(exist = false)
List<TStudent> studentList;
}
TStudent
@Data
public class TStudent extends Model<TStudent> {
private static final long serialVersionUID = 1L;
private String id;
private String name;
private String card;
private String classid;
@TableField(exist = false)
private TClass tClass;
}
二、一对多
一、嵌套结果 方式
1、mapper接口
List<TClass> getClassList();
2、service和serviceImpl省略
3、xml文件
<!-- 嵌套结果 -->
<resultMap id="classMap1" type="com.example.aaa.test.entity.TClass">
<id column="id" property="id" />
<result column="name" property="name" />
<result column="code" property="code" />
<collection property="studentList" ofType="com.example.aaa.test.entity.TStudent">
<id column="sid" property="id" />
<result column="sname" property="name" />
<result column="card" property="card" />
<result column="classid" property="classid" />
</collection>
</resultMap>
<select id="getClassList" resultMap="classMap1">
SELECT
c.id,
c.name,
c.code,
s.id as sid,
s.name as sname,
s.card,
s.classid
FROM
t_class c
LEFT JOIN t_student s ON s.classid = c.id
</select>
嵌套结果,在使用的时候需要注意名称相同的字段,需要用别名,在result的column中,需要使用对应的别名
二、嵌套查询 方式
1、mapper接口
List<TClass> getClasses();
2、service接口和serviceImpl省略
3、xml文件
<resultMap id="classMap2" type="com.example.aaa.test.entity.TClass">
<id column="id" property="id" />
<result column="name" property="name" />
<result column="code" property="code" />
<collection property="studentList"
column="{sid=id}"
select="getStudentByCid"
ofType="com.example.aaa.test.entity.TStudent">
<id column="id" property="id" />
<result column="name" property="name" />
<result column="card" property="card" />
<result column="classid" property="classid" />
</collection>
</resultMap>
<!--主查询-->
<select id="getClasses" resultMap="classMap2">
select id,name,code from t_class;
</select>
<!--子查询-->
<select id="getStudentByCid" resultType="com.example.aaa.test.entity.TStudent">
select id,name,card,classid from t_student where classid=#{sid};
</select>
collection标签的解释:
1.property是子查询封装的结果,对应到主查询的哪个属性
2.column是将查询结果中的参数,传递到子查询中{sid=id},id必须出现在父查询的结果集中,子查询中要使用sid
3.select是调用的子查询的语句,不需要在mapper接口中额外添加
4.ofType是封装的List集合中对象的类型
4、controller调用
@RequestMapping("/getClassList")
public Object getStudentList(){
List<TClass> list = tClassService.getClassList();
return list;
}
@RequestMapping("/getClasses")
public Object getStudens(){
List<TClass> list = tClassService.getClasses();
return list;
}
嵌套结果和嵌套查询,查询结果一样,如图:
三、多对一
一、嵌套结果 方式
1、mapper接口
List<TStudent> getStudentList();
2、service和serviceImpl省略
3、xml文件
<!-- 嵌套结果 -->
<resultMap id="StudentMap1" type="com.example.aaa.test.entity.TStudent">
<id column="id" property="id" />
<result column="name" property="name" />
<result column="card" property="card" />
<result column="classid" property="classid" />
<association property="tClass" javaType="com.example.aaa.test.entity.TClass">
<!-- 含义:cid对应的是TClass类中的id;column=cid是查出结果中的别名,因为id和上面的id重名,所以用别名 -->
<id column="cid" property="id"></id>
<!-- 同理,cname也需要用别名,因为和上面的name重复了 -->
<result column="cname" property="name" />
<!-- code不需要别名,因为code是唯一的 -->
<result column="code" property="code" />
</association>
</resultMap>
<select id="getStudentList" resultMap="StudentMap1">
SELECT
s.id,
s.name,
s.classid,
s.card,
c.id AS cid,
c.name AS cname,
c.code
FROM
t_student s
LEFT JOIN t_class c ON s.classid = c.id
</select>
二、嵌套查询 方式
1、mapper接口
List<TClass> getClasses();
2、service和serviceImpl省略
3、xml文件
<!--嵌套查询-->
<resultMap id="StudentMap2" type="com.example.aaa.test.entity.TStudent">
<id column="id" property="id" />
<result column="name" property="name" />
<result column="card" property="card" />
<result column="classid" property="classid" />
<!--
property=tClass是Student中的属性
select="getClassBySid"是要调用的子查询
column="{cid=classid}"是要传入子查询中的参数,就是结果集中的classid赋值给cid,子查询用cid查询
JavaType是子查询结果的类型
-->
<association property="tClass"
column="{cid=classid}"
javaType="com.example.aaa.test.entity.TClass"
select="getClassBySid">
<!--不会出现重名,所以不需要改别名-->
<id column="id" property="id"></id>
<result column="name" property="name" />
<result column="code" property="code" />
</association>
</resultMap>
<select id="getStudents" resultMap="StudentMap2">
SELECT
id,
name,
classid,
card
FROM
t_student
</select>
<!--子查询不需要在mapper的接口中额外添加-->
<select id="getClassBySid" resultType="com.example.aaa.test.entity.TClass">
SELECT
id,
name,
code
FROM t_class
<!--cid是从父查询传递过来的-->
where id=#{cid}
</select>
4、controller调用
@RequestMapping("/getStudentList")
public Object getStudentList(){
List<TStudent> list = tStudentService.getStudentList();
return list;
}
@RequestMapping("/getStudents")
public Object getStudens(){
List<TStudent> list = tStudentService.getStudents();
return list;
}
嵌套结果和嵌套查询,查询结果相同,如图: