Mybatis的多对一和一对多处理
Mybatis的多对一和一对多
1.Lombok
首先我们来看下Lombok,百度搜以下Lombok,找到官网:https://projectlombok.org/
官网有这么一句话:
Project Lombok is a java library that automatically plugs into your editor and build tools, spicing up your java.
Never write another getter or equals method again, with one annotation your class has a fully featured builder, Automate your logging variables, and much more.
使用步骤:
1.在IDEA中安装Lombok插件!
2.在项目中导入lombok的jar包
直接去maven仓库官网搜 Lombok maven
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
<scope>provided</scope>
</dependency>
3.在实体类上加注解即可
Lombok有以下的注解可供使用:
@Getter and @Setter
@FieldNameConstants
@ToString
@EqualsAndHashCode
@AllArgsConstructor, @RequiredArgsConstructor and @NoArgsConstructor
@Log, @Log4j, @Log4j2, @Slf4j, @XSlf4j, @CommonsLog, @JBossLog, @Flogger, @CustomLog
@Data
@Builder
@SuperBuilder
@Singular
@Delegate
@Value
@Accessors
@Wither
@With
@SneakyThrows
@val
@var
说明:
@Data: 无参构造、getter、setter、toString、hashcode、equals
@AllArgsConstructor:有参构造
@NoArgsConstructor:无参构造
@ToString:生成toString方法
@EqualsAndHashCode:生成equeals和hashcode方法
2.多对一处理
多对一
- 多个学生,对应一个老师
- 对于学生这边而言,和老师存在关联关系,多个学生关联一个老师【多对一】
- 对于老师而言,和学生存在集合关系,一个老师有很对学生【一对多】
搭建复杂环境用的SQL:
CREATE TABLE `teacher` (
`id` INT(10) NOT NULL,
`name` VARCHAR(30) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8
INSERT INTO teacher(`id`, `name`) VALUES (1,"秦老师");
CREATE TABLE `student` (
`id` INT(10) NOT NULL,
`name` VARCHAR(30) DEFAULT NULL,
`tid` INT(10) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `fktid` (`tid`),
CONSTRAINT `fktid` FOREIGN KEY (`tid`) REFERENCES `teacher` (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8
INSERT INTO `student` (`id`, `name`, `tid`) VALUES (1, "小明", 1);
INSERT INTO `student` (`id`, `name`, `tid`) VALUES (2, "小红", 1);
INSERT INTO `student` (`id`, `name`, `tid`) VALUES (3, "小张", 1);
INSERT INTO `student` (`id`, `name`, `tid`) VALUES (4, "小李", 1);
INSERT INTO `student` (`id`, `name`, `tid`) VALUES (5, "小王", 1);
测试环境搭建
1.导入Lombok
2.新建实体类Teacher、Student
3.建立Mapper接口
4.建立Mapper.xml文件
5.在核心配置文件中绑定注册我们的mapper接口或者文件
6.测试查询是否能够成功
以上不走不用多说,前面搭建过很多次
这里主要注意一点:mapper接口文件放在src/main/java的某个目录(com/kuang/dao)下面和mapper.xml文件放在src/main/resource的对应目录下面,在打包后都会被打包到classpath下面,也就是classes目录下面。并且会被合并到同一目录下(因为目录都是com/kuang/dao),如图:
现在我们来写一下多对一
按照查询嵌套处理
<!--
思路:
1.查询所有的学生信息
2.根据查询出来的学生的tid,寻找对应的老师!
-->
<resultMap id="StudentTeacher" type="Student">
<result property="id" column="id"/>
<result property="name" column="name"/>
<!--复杂的属性,我们需要单独处理
对象:association
集合:collection
-->
<association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/>
</resultMap>
<select id="getStudent" resultMap="StudentTeacher">
select * from student;
</select>
<select id="getTeacher" resultType="Teacher">
select * from teacher where id = #{id}
</select>
按照结果嵌套查询
<!--按照结果嵌套处理-->
<select id="getStudent2" resultMap="StudentTeacher2">
select s.id sid,s.name sname,t.`name` tname from student s,teacher t where s.tid = t.id
</select>
<resultMap id="StudentTeacher2" type="Student">
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<association property="teacher" javaType="Teacher">
<result property="name" column="tname"/>
</association>
</resultMap>
回顾Mysql多对一查询方式:
- 子查询: 相当于按照查询嵌套处理
- 联表查询:相当于按照结果嵌套处理
3.一对多处理
比如:一个老师拥有多个学生!
对于老师而言,就是一对多的关系!
1.环境搭建
环境搭建和刚才一样
实体类
@Data
public class Student {
private int id;
private String name;
private int tid;
}
@Data
public class Teacher {
private int id;
private String name;
//一个老师拥有多个学生
private List<Student> students;
}
按照结果嵌套处理
就是相当于复杂sql写完了,本身数据查询出来就是一个集合的形式,最终我们要封装成一个实体类Teacher的形式,但是属性名和sql查出来的字段名不一致,用collection标签做如下处理即可:
<!--按结果嵌套查询-->
<select id="getTeacher" resultMap="TeacherStudent">
select s.id sid,s.name sname,t.name tname,t.id tid
from student s,teacher t where s.tid = t.id
and t.id=#{tid}
</select>
<resultMap id="TeacherStudent" type="Teacher">
<result property="id" column="tid"/>
<result property="name" column="tname"/>
<!--
复杂类型我们需要单独处理:
对象:association
集合:collection
javaType="" 指定属性的类型
集合中的泛型信息,我们使用ofType获取
-->
<collection property="students" ofType="Student">
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<result property="tid" column="tid"/>
</collection>
</resultMap>
按照查询嵌套处理
按照查询嵌套处理的话:这是另一种思路,就是先查老师,由于第一个sql只查出了老师的id和name,需要用collection标签用如下方法将老师的id传给下面另一个sql语句,就能够查询改老师下所有的学生并封装到实体类list集合当中。
这里须注意如果resultMap中不加 ,则查不出老师的id的!
<!--按照查询嵌套处理-->
<select id="getTeacher2" resultMap="TeacherStudent2">
select * from teacher where id=#{tid}
</select>
<resultMap id="TeacherStudent2" type="Teacher">
<result property="id" column="id"/>
<collection property="students" javaType="ArrayList" ofType="Student"
select="getStudentByTeacherId" column="id"/>
</resultMap>
<select id="getStudentByTeacherId" resultType="Student">
select * from student where tid=#{id}
</select>
4.小结
1.关联 – association 【多对一】
2.集合 – collection 【一对多】
3.javaType :用来指定实体类中属性的类型,ofType:用来指定映射到list或者集合中的pojo类型,泛型中的约束类型!
综合:无论是多对一还是一对多,都建议使用按结果嵌套处理的方式来做,因为出了问题,按查询嵌套处理并不好调试!(想想,按结果嵌套处理的方式还可以调试下sql,但按查询嵌套处理怎么调呢?)
注意点:
- 保证SQL的可读性,尽量保证通俗易懂
- 注意一对多和多对一中,属性名和字段的问题!
- 如果问题不好排查错误,可以使用日志!
这篇文章的源码在Mybatis-study工程的mybatis-06和mybatis-07模块下!,后面会给出码云地址。