Mybatis的嵌套关联查询案例实战
Posted 北溟溟
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mybatis的嵌套关联查询案例实战相关的知识,希望对你有一定的参考价值。
前言
在Mybatis使用中,我们经常要处理一对一、一对多以及多层嵌套的关系。本节我们通过俩种方式分别实现一对一、一对多以及多层嵌套的mybatis查询案例,俩种方式各有优劣,其中一种可以实现懒加载的效果。闲话少说,我们开始正文。
正文
- 创建业务关系表及测试数据
说明:班级和学生是一对多的关系,学生和职务是一对一的关系
①创建班级表
CREATE TABLE `class` ( `id` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '主键', `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '名称', PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '班级' ROW_FORMAT = Dynamic;
② 创建学生表
CREATE TABLE `student` ( `id` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '主键', `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '名字', `class_id` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '所属年级', `duty_id` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '职务', PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '学生' ROW_FORMAT = Dynamic;
③创建学生职务表
CREATE TABLE `duty` ( `id` int(0) NOT NULL COMMENT '主键', `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '职务', PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '职务表' ROW_FORMAT = Dynamic;
④测试数据
INSERT INTO `class` VALUES ('1', '一年级');
INSERT INTO `class` VALUES ('2', '二年级');
INSERT INTO `class` VALUES ('3', '三年级');
INSERT INTO `class` VALUES ('4', '四年级');
INSERT INTO `class` VALUES ('5', '五年级');
INSERT INTO `class` VALUES ('6', '六年级');
INSERT INTO `duty` VALUES (1, '班长');
INSERT INTO `duty` VALUES (2, '学习委员');
INSERT INTO `duty` VALUES (3, '劳动委员');
INSERT INTO `duty` VALUES (4, '小组长');
INSERT INTO `duty` VALUES (5, '无职务');
INSERT INTO `student` VALUES ('1', '张三', '1', '1');
INSERT INTO `student` VALUES ('2', '李四', '1', '2');
INSERT INTO `student` VALUES ('3', '赵六', '1', '3');
INSERT INTO `student` VALUES ('4', '王五', '2', '4');
INSERT INTO `student` VALUES ('5', 'tom', '3', '5');
INSERT INTO `student` VALUES ('6', 'jack', '2', '5');
- 案例一:一对一关联查询
①控制层
@Api(tags = "学生管理接口")
@RestController
@RequestMapping("/test/student")
public class StudentController {
@Autowired
private StudentService studentService;
@ApiOperation(value = "方式一:获取所有学生及学生职务详情数据")
@GetMapping(value = "getAllStudentDutyListByOne")
public Result getAllStudentDutyListByOne(){
List<Student> students = studentService.getAllStudentDutyListByOne();
return Result.success(students);
}
@ApiOperation(value = "方式二:获取所有学生及学生职务详情数据")
@GetMapping(value = "getAllStudentDutyListByTwo")
public Result getAllStudentDutyListByTwo(){
List<Student> students = studentService.getAllStudentDutyListByTwo();
return Result.success(students);
}
}
②业务接口层
public interface StudentService extends IService<Student> {
/**
* 方式一:获取所有学生及学生职务详情数据
* @return
*/
List<Student> getAllStudentDutyListByOne();
/**
* 方式二:获取所有学生及学生职务详情数据
* @return
*/
List<Student> getAllStudentDutyListByTwo();
}
③业务接口实现层
@Service
public class StudentServiceImpl extends ServiceImpl<StudentMapper, Student> implements StudentService {
@Override
public List<Student> getAllStudentDutyListByOne() {
return baseMapper.getAllStudentDutyListByOne();
}
@Override
public List<Student> getAllStudentDutyListByTwo() {
return baseMapper.getAllStudentDutyListByTwo();
}
}
④数据持久化层
public interface StudentMapper extends BaseMapper<Student> {
/**
* 方式一:获取所有学生及学生职务详情数据
* @return
*/
List<Student> getAllStudentDutyListByOne();
/**
* 方式二:获取所有学生及学生职务详情数据
* @return
*/
List<Student> getAllStudentDutyListByTwo();
}
⑤实体类
@Data
@EqualsAndHashCode(callSuper = false)
@ApiModel(value="Student对象", description="学生")
public class Student implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "主键")
private String id;
@ApiModelProperty(value = "名字")
private String name;
@ApiModelProperty(value = "所属年级")
private String classId;
@ApiModelProperty(value = "职务")
private String dutyId;
@TableField(exist = false)
private Duty duty;
}
@Data
@EqualsAndHashCode(callSuper = false)
@ApiModel(value="Duty对象", description="职务表")
public class Duty implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "主键")
private Integer id;
@ApiModelProperty(value = "职务")
private String name;
}
⑥xml层
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yundi.atp.platform.module.test.mapper.StudentMapper">
<!--方式一-->
<resultMap id="getAllStudentDutyListByOne" type="com.yundi.atp.platform.module.test.entity.Student">
<id column="id" property="id"></id>
<result column="name" property="name"></result>
<result column="class_id" property="classId"></result>
<result column="duty_id" property="dutyId"></result>
<association property="duty" javaType="com.yundi.atp.platform.module.test.entity.Duty">
<id column="dutyId" property="id"></id>
<result column="dutyName" property="name"></result>
</association>
</resultMap>
<select id="getAllStudentDutyListByOne" resultMap="getAllStudentDutyListByOne">
select t.id,t.name,t.class_id,t.duty_id,t1.id as dutyId,t1.name as dutyName from student t inner join duty t1 on t1.id = t.duty_id
</select>
<!--方式二-->
<resultMap id="getAllStudentDutyListByTwo" type="com.yundi.atp.platform.module.test.entity.Student">
<id column="id" property="id"></id>
<result column="name" property="name"></result>
<result column="class_id" property="classId"></result>
<result column="duty_id" property="dutyId"></result>
<association property="duty" javaType="com.yundi.atp.platform.module.test.entity.Duty" select="getDutyByStuID" column="duty_id"></association>
</resultMap>
<select id="getAllStudentDutyListByTwo" resultMap="getAllStudentDutyListByTwo">
select id,name,class_id,duty_id from student
</select>
<select id="getDutyByStuID" resultType="com.yundi.atp.platform.module.test.entity.Duty">
select t.id,t.name from duty t where t.id = #{duty_id}
</select>
</mapper>
测试结果
①一对一关联查询方式一测试结果
②一对一关联查询方式二测试结果
- 案例二:一对多关联查询及多级嵌套查询
①控制层
@Api(tags = "班级管理接口")
@RestController
@RequestMapping("/test/class")
public class ClassController {
@Autowired
private ClassService classService;
@ApiOperation(value = "方式一:获取所有班级下的所有学生详情数据")
@GetMapping(value = "getAllClassStudentListByOne")
public Result getAllClassStudentListByOne() {
List<Class> classes = classService.getAllClassStudentListByOne();
return Result.success(classes);
}
@ApiOperation(value = "方式二:获取所有班级下的所有学生详情数据")
@GetMapping(value = "getAllClassStudentListByTwo")
public Result getAllClassStudentListByTwo() {
List<Class> classes = classService.getAllClassStudentListByTwo();
return Result.success(classes);
}
@ApiOperation(value = "方式一:获取所有班级下的所有学生及职务详情数据")
@GetMapping(value = "getAllClassStudentDutyListByOne")
public Result getAllClassStudentDutyListByOne() {
List<Class> classes = classService.getAllClassStudentDutyListByOne();
return Result.success(classes);
}
@ApiOperation(value = "方式二:获取所有班级下的所有学生及职务详情数据")
@GetMapping(value = "getAllClassStudentDutyListByTwo")
public Result getAllClassStudentDutyListByTwo() {
List<Class> classes = classService.getAllClassStudentDutyListByTwo();
return Result.success(classes);
}
}
②业务接口层
public interface ClassService extends IService<Class> {
/**
* 方式一:获取所有班级下的所有学生详情数据
* @return
*/
List<Class> getAllClassStudentListByOne();
/**
* 方式二:获取所有班级下的所有学生详情数据
* @return
*/
List<Class> getAllClassStudentListByTwo();
/**
* 方式一:获取所有班级下的所有学生及职务详情数据
* @return
*/
List<Class> getAllClassStudentDutyListByOne();
/**
* 方式二:获取所有班级下的所有学生及职务详情数据
* @return
*/
List<Class> getAllClassStudentDutyListByTwo();
}
③业务接口实现层
public interface ClassMapper extends BaseMapper<Class> {
/**
* 方式一:获取所有班级下的所有学生详情数据
* @return
*/
List<Class> getAllClassStudentListByOne();
/**
* 方式二:获取所有班级下的所有学生详情数据
* @return
*/
List<Class> getAllClassStudentListByTwo();
/**
* 方式一:获取所有班级下的所有学生及职务详情数据
* @return
*/
List<Class> getAllClassStudentDutyListByOne();
/**
* 方式二:获取所有班级下的所有学生及职务详情数据
* @return
*/
List<Class> getAllClassStudentDutyListByTwo();
}
④数据持久化层
public interface ClassMapper extends BaseMapper<Class> {
/**
* 方式一:获取所有班级下的所有学生详情数据
* @return
*/
List<Class> getAllClassStudentListByOne();
/**
* 方式二:获取所有班级下的所有学生详情数据
* @return
*/
List<Class> getAllClassStudentListByTwo();
/**
* 方式一:获取所有班级下的所有学生及职务详情数据
* @return
*/
List<Class> getAllClassStudentDutyListByOne();
/**
* 方式二:获取所有班级下的所有学生及职务详情数据
* @return
*/
List<Class> getAllClassStudentDutyListByTwo();
}
⑤实体类
@Data
@EqualsAndHashCode(callSuper = false)
@ApiModel(value="Class对象", description="班级")
public class Class implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "主键")
private String id;
@ApiModelProperty(value = "名称")
private String name;
@TableField(exist = false)
private List<Student> studentList;
}`
@Data
@EqualsAndHashCode(callSuper = false)
@ApiModel(value="Duty对象", description="职务表")
public class Duty implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "主键")
private Integer id;
@ApiModelProperty(value = "职务")
private String name;
}
@Data
@EqualsAndHashCode(callSuper = false)
@ApiModel(value="Student对象", description="学生")
public class Student implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "主键")
private String id;
@ApiModelProperty(value = "名字")
private String name;
@ApiModelProperty(value = "所属年级")
private String classId;
@ApiModelProperty(value = "职务")
private String dutyId;
@TableField(exist = false)
private Duty duty;
}
⑥xml层
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yundi.atp.platform.module.test.mapper.ClassMapper">
<!--方式一:一对多嵌套查询-->
<resultMap id="getAllClassStudentListByOne" type="com.yundi.atp.platform.module.test.entity.Class">
<id column="id" property="id"></id>
<result column="name" property="name"></result>
<collection property="studentList" ofType="com.yundi.atp.platform.module.test.entity.Student"
javaType="ArrayList">
<id property="id" column="stuId"></id>
<result property="name" column="stuName"></result>
</collection>
</resultMap>
<select id="getAllClassStudentListByOne" resultMap="getAllClassStudentListByOne">
select t.id,t.name,t1.id as stuId,t1.name as stuName from class t left join student t1 on t1.class_id = t.id
</select>
<resultMap id="getAllClassStudentListByTwo" type="com.yundi.atp.platform.module.test.entity.Class">
<id column="id" property="id"></id>
<result column="name" property="name"></result>
<collection property="studentList" ofType="com.yundi.atp.platform.module.test.entity.Student"
javaType="ArrayList" column="id" select="getStudents"></collection>
</resultMap>
<!--方式二:一对多嵌套查询-->
<select id="getAllClassStudentListByTwo" resultMap="getAllClassStudentListByTwo">
select id,name from class
</select>
<select id="getStudents" resultType="com.yundi.atp.platform.module.test.entity.Student">
select id,name from student where class_id = #{classId}
</select>
<resultMap id="getAllClassStudentDutyListByOne" type="com.yundi.atp.platform.module.test.entity.Class">
<id column="id" property="id"></id>
<result column="name" property="name"></result>
<collection property="studentList" ofType="com.yundi.atp.platform.module.test.entity.Student"
javaType="ArrayList">
<id property="id" column="stuId"></id>
<result property="name" column="stuName"></result>
<result property="dutyId" column="stuDutyId"></result>
<association property="duty" javaType="com.yundi.atp.platform.module.test.entity.Duty">
<id column="dutyId" property="id"></id>
<result column="dutyName" property="name"></result>
</association>
</collection>
</resultMap>
<!--方式一:多级嵌套查询-->
<select id="getAllClassStudentDutyListByOne" resultMap="getAllClassStudentDutyListByOne">
select t.id,t.name,t1.id as stuId,t1.name as stuName,t1.duty_id as stuDutyId,t2.id as dutyId,t2.name as dutyName from class t left join student t1 on t1.class_id = t.id left join duty t2 on t2.id = t1.duty_id
</select>
<resultMap id="getAllClassStudentDutyListByTwo" type="com.yundi.atp.platform.module.test.entity.Class">
<id column="id" property="id"></id>
<result column="name" property="name"></result>
<collection property="studentList" ofType="com.yundi.atp.platform.module.test.entity.Student"
javaType="ArrayList" column="id" select="getStudentList"></collection>
</resultMap>
<!--方式二:多级嵌套查询-->
<select id="getAllClassStudentDutyListByTwo" resultMap="getAllClassStudentDutyListByTwo">
select id,name from class
</select>
<resultMap id="getStudentList" type="com.yundi.atp.platform.module.test.entity.Student">
<id column="id" property="id"></id>
<result column="name" property="name"></result>
<result column="duty_id" property="dutyId"></result>
<association property="duty" javaType="com.yundi.atp.platform.module.test.entity.Duty" column="duty_id"
select="getDuty"></association>
</resultMap>
<select id="getStudentList" resultMap="getStudentList">
select id,name,duty_id from student where class_id = #{classId}
</select>
<select id="getDuty" resultType="com.yundi.atp.platform.module.test.entity.Duty">
select t.id,t.name from duty t where t.id = #{duty_id}
</select>
</mapper>
测试结果
①一对多关联查询方式一测试结果
②一对多关联查询方式二测试结果
③多级关联查询方式一结果
④多级关联查询方式二结果
结语
ok,到这里我们Mybatis的嵌套关联查询案例实战就结束了,希望能对你有所帮助,我们下期见!
以上是关于Mybatis的嵌套关联查询案例实战的主要内容,如果未能解决你的问题,请参考以下文章
mybatis实战教程(mybatis in action)之四:实现关联数据的查询