工作中常常会碰到联表查询,最近刚刚参加工作,在写查询时发现自己很不熟练,特此总结一下一对一和一对多的查询。
学习时使用的是MyBatis,参加工作了开始学习使用MyBatis-Plus。关于这两者的使用后续会进行总结,在前辈那里得来的结论是:
MyBatis-Plus ⊇ MyBatis
当然需要自己进行操作使用后再来回头总结。本篇使用的是MyBatis-Plus。
在Dao层写sql语句时,我们常用的标签诸如select、update、delete、insert、where、if等等,都需要非常熟悉,我认为这也是代码的基本功吧,关于一对一和一对多,这里使用到的关键标签就是association和collection。
依赖:
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-boot-starterartifactId>
<version>3.5.2version>
dependency>
application配置文件:
server:
port: 9999
spring:
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/class
username: root
password: 123
mybatis-plus:
mapper-locations: classpath*:/mappers/*Mapper.xml
数据库:
三张表:班级、老师、学生,数据若干。这里没有使用外键,在工作中其实不常使用外键,外键使用过多会造成数据库维护成本过高!
-- ----------------------------
-- Table structure for class
-- ----------------------------
DROP TABLE IF EXISTS `class`;
CREATE TABLE `class` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '班级',
`head_teacher_id` int(11) DEFAULT NULL COMMENT '班主任',
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of class
-- ----------------------------
INSERT INTO `class` VALUES ('1', '1');
INSERT INTO `class` VALUES ('2', '2');
INSERT INTO `class` VALUES ('3', '3');
-- ----------------------------
-- Table structure for student
-- ----------------------------
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '学生id',
`name` varchar(255) DEFAULT NULL COMMENT '学生姓名',
`class_id` int(11) DEFAULT NULL COMMENT '班级id',
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=11 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of student
-- ----------------------------
INSERT INTO `student` VALUES ('1', '张三', '1');
INSERT INTO `student` VALUES ('2', '李四', '2');
INSERT INTO `student` VALUES ('3', '王雯雯', '1');
INSERT INTO `student` VALUES ('4', '刘文涛', '3');
INSERT INTO `student` VALUES ('5', '卢毅', '1');
INSERT INTO `student` VALUES ('6', '李晓楠', '2');
INSERT INTO `student` VALUES ('7', '陈果', '2');
INSERT INTO `student` VALUES ('8', '唐浩', '3');
INSERT INTO `student` VALUES ('9', '秦琴', '3');
INSERT INTO `student` VALUES ('10', '王梦娟', '1');
-- ----------------------------
-- Table structure for teacher
-- ----------------------------
DROP TABLE IF EXISTS `teacher`;
CREATE TABLE `teacher` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '老师id',
`name` varchar(255) DEFAULT NULL COMMENT '老师名字',
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of teacher
-- ----------------------------
INSERT INTO `teacher` VALUES ('1', '张江');
INSERT INTO `teacher` VALUES ('2', '王闻彦');
INSERT INTO `teacher` VALUES ('3', '周倩');
INSERT INTO `teacher` VALUES ('4', '李强');
实体类:
班级
@Data
public class Classes {
private Integer id;
private Integer headTeacherId;
private Teacher headTeacher;
private List<Student> students;
}
老师
@Data
public class Teacher {
private Integer id;
private String name;
}
学生
@Data
public class Student {
private Integer id;
private String name;
private Integer classId;
}
这里要说明一下,工作中,班级类的老师和学生这两个属性是不该这样写的,实体类是和数据库中的字段一一对应的,实际工作会按照需求自行创建DTO或者VO类,这里为了省事就这就样直接写了。
目标:查出班级的同时要把老师的信息查出来
<resultMap id="classResultMap" type="com.example.mybatisplus.entity.Classes">
<id column="id" property="id"/>
<result column="head_teacher_id" property="headTeacherId"/>
<association property="headTeacher"
column="head_teacher_id"
javaType="com.example.mybatisplus.entity.Teacher"
select="queryTeacherById"/>
resultMap>
<select id="queryById" resultMap="classResultMap">
SELECT * FROM classes WHERE id = #{id}
select>
<select id="queryTeacherById" resultType="com.example.mybatisplus.entity.Teacher">
SELECT * FROM teacher WHERE id = #{id}
select>
说明:
<resultMap id="classResultMap" type="com.example.mybatisplus.entity.Classes">
<id column="id" property="id"/>
<result column="head_teacher_id" property="headTeacherId"/>
<association property="headTeacher" javaType="com.example.mybatisplus.entity.Teacher">
<id property="id" column="id"/>
<result property="name" column="name"/>
association>
resultMap>
<select id="queryById" resultMap="classResultMap">
SELECT * FROM classes c LEFT JOIN teacher t ON c.head_teacher_id = t.id WHERE c.id = #{id}
select>
说明:
结果展示:
目标:查出班级的同时要把所有学生的信息查出来
<resultMap id="classResultMap" type="com.example.mybatisplus.entity.Classes">
<id column="id" property="id"/>
<result column="head_teacher_id" property="headTeacherId"/>
<association property="headTeacher" column="id"
javaType="com.example.mybatisplus.entity.Teacher"
select="queryTeacherById"/>
<collection property="students"
column="id"
ofType="com.example.mybatisplus.entity.Student"
select="queryStudentByClassId"/>
resultMap>
<select id="queryStudentByClassId" resultType="com.example.mybatisplus.entity.Student">
SELECT * FROM student WHERE class_id = #{id}
select>
<select id="queryById" resultMap="classResultMap">
SELECT * FROM classes c LEFT JOIN teacher t ON c.head_teacher_id = t.id WHERE c.id = #{id}
select>
<select id="queryTeacherById" resultType="com.example.mybatisplus.entity.Teacher">
SELECT * FROM teacher WHERE id = #{id}
select>
说明:
<resultMap id="classResultMap" type="com.example.mybatisplus.entity.Classes">
<id column="id" property="id"/>
<result column="head_teacher_id" property="headTeacherId"/>
<association property="headTeacher" javaType="com.example.mybatisplus.entity.Teacher">
<id column="t_id" property="id"/>
<result column="t_name" property="name"/>
association>
<collection property="students" javaType="list" ofType="com.example.mybatisplus.entity.Student">
<id column="s_id" property="id"/>
<result column="s_name" property="name"/>
<result column="s_class_id" property="classId"/>
collection>
resultMap>
<select id="queryById" resultMap="classResultMap">
SELECT c.*, t.id t_id, t.name t_name, s.id s_id, s.name s_name, s.class_id s_class_id FROM classes c
LEFT JOIN teacher t ON c.head_teacher_id = t.id
LEFT JOIN student s ON s.class_id = c.id
WHERE c.id = #{id}
select>
说明:
结果展示:
关于MyBatis和MyBatis-Plus的使用本人并不是很熟悉,以上写法只是我在工作中容易碰到的,所以进行一个总结,怕自己容易忘。
本人今年刚毕业,第一次写博客,若有错漏之处或者更优雅写法请评论区友好指出,谢谢!