MyBatis中多对一和一对多数据的处理
多对一的处理
多对一的理解:
- 多个学生对应一个老师
- 如果对于学生这边,就是一个多对一的现象,即从学生这边关联一个老师!
1、数据库设计
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 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' ); |
2、搭建测试环境
【Lombok的使用】
1. IDEA安装Lombok插件
2. 引入Maven依赖
1 2 3 4 5 | <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version> 1.16 . 10 </version> </dependency> |
3. 在代码中增加注解
1 2 3 4 5 | @Data public class Teacher { private int id; private String name; } |
1 2 3 4 5 6 7 | @Data public class Student { private int id; private String name; //多个学生可以是同一个老师,即多对一 private Teacher teacher; } |
4. 编写实体类对应的Mapper接口 【两个】
- 无论有没有需求,都应该写上,以备后来之需!
1 2 | public interface StudentMapper { } |
1 2 | public interface TeacherMapper { } |
5. 编写Mapper接口对应的 mapper.xml配置文件 【两个】
- 无论有没有需求,都应该写上,以备后来之需!
1 2 3 4 5 6 | <?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.hang.mapper.StudentMapper" > </mapper> |
1 2 3 4 5 6 | <?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.hang.mapper.TeacherMapper" > </mapper> |
3、按查询嵌套处理
1. 给StudentMapper接口增加方法
1 2 | //获取所有学生及对应老师的信息 public List<Student> getStudents(); |
2. 编写对应的Mapper文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | <?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.hang.mapper.StudentMapper" > <select id= "getStudents" resultMap= "studentTeacher" > select * from mybatis.student; </select> <resultMap id= "studentTeacher" type= "student" > <result property= "id" column= "id" /> <result property= "name" column= "name" /> <!--association关联属性 property属性名 javaType属性类型 column在多的一方的表中的列名--> <association property= "teacher" column= "tid" javaType= "teacher" select= "getTeacher" /> </resultMap> <select id= "getTeacher" resultType= "teacher" > select * from mybatis.teacher; </select> </mapper> |
3. 编写完毕去Mybatis配置文件中,注册Mapper!
4. 测试
1 2 3 4 5 6 7 8 9 10 11 12 | @Test public void getStudents(){ SqlSession sqlSession = MybatisUtils.getSqlSession(); StudentMapper mapper = sqlSession.getMapper(StudentMapper. class ); List<Student> students= mapper.getStudents(); for (Student student : students) { System.out.println( "学生名:" + student.getName() + "\t老师:" +student.getTeacher().getName()); } sqlSession.close(); } |
4 、按结果嵌套处理
除了上面这种方式,还有其他思路吗?
我们还可以按照结果进行嵌套处理;
1. 接口方法编写
1 | public List<Student> getStudents2(); |
2. 编写对应的mapper文件
1 2 3 4 5 6 7 8 9 10 11 12 13 | <select id= "getStudents2" resultMap= "studentTeacher2" > select s.id sid, s.name sname, t.id tid, t.name tname from mybatis.student s, mybatis.teacher t where t.id = s.tid </select><br> <resultMap id= "studentTeacher2" type= "student" > <result property= "id" column= "sid" /> <result property= "name" column= "sname" /> <association property= "teacher" javaType= "teacher" > <result property= "id" column= "tid" /> <result property= "name" column= "tname" /> </association> </resultMap> |
3. 去mybatis-config文件中注入【此处应该处理过了】
4. 测试
1 2 3 4 5 6 7 8 9 10 11 12 | @Test public void getStudents2(){ SqlSession sqlSession = MybatisUtils.getSqlSession(); StudentMapper mapper = sqlSession.getMapper(StudentMapper. class ); List<Student> students= mapper.getStudents2(); for (Student student : students) { System.out.println( "学生名:" + student.getName() + "\t老师:" +student.getTeacher().getName()); } sqlSession.close(); } |
5、小结
- 按照查询进行嵌套处理就像SQL中的子查询
- 按照结果进行嵌套处理就像SQL中的联表查询
一对多的处理
一对多的理解:
- 一个老师拥有多个学生
- 如果对于老师这边,就是一个一对多的现象,即从一个老师下面拥有一群学生(集合)!
1、实体类编写
1 2 3 4 5 6 | @Data public class Student { private int id; private String name; private int tid; } |
1 2 3 4 5 6 7 | @Data public class Teacher { private int id; private String name; //一个老师多个学生 private List<Student> students; } |
和之前一样,搭建测试的环境!
2、按结果嵌套处理
1. TeacherMapper接口编写方法
1 2 | //获取指定老师,及老师下的所有学生 public Teacher getTeacher( int id); |
2. 编写接口对应的Mapper配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <select id= "getTeacher" resultMap= "TeacherStudent" > select s.id sid, s.name sname, t.id tid, t.name tname from mybatis.teacher t, mybatis.student s where t.id = s.tid and t.id = #{tid}; </select> <resultMap id= "TeacherStudent" type= "teacher" > <result property= "id" column= "tid" /> <result property= "name" column= "tname" /> <collection property= "students" ofType= "student" > <result property= "id" column= "sid" /> <result property= "name" column= "sname" /> <result property= "tid" column= "tid" /> </collection> </resultMap> |
3. 将Mapper文件注册到MyBatis-config文件中
4. 测试
1 2 3 4 5 6 7 8 | @Test public void testGetTeacher(){ SqlSession session = MybatisUtils.getSession(); TeacherMapper mapper = session.getMapper(TeacherMapper. class ); Teacher teacher = mapper.getTeacher( 1 ); System.out.println(teacher.getName()); System.out.println(teacher.getStudents()); } |
3、按查询嵌套处理
1. TeacherMapper接口编写方法
1 | public Teacher getTeacher2( int id); |
2. 编写接口对应的Mapper配置文件
1 2 3 4 5 6 7 8 9 10 | <select id= "getTeacher2" resultMap= "TeacherStudent2" > select * from teacher where id = #{id} </select> <resultMap id= "TeacherStudent2" type= "Teacher" > <!--column是一对多的外键 , 写的是一的主键的列名--> <collection property= "students" javaType= "ArrayList" ofType= "Student" column= "id" select= "getStudentByTeacherId" /> </resultMap> <select id= "getStudentByTeacherId" resultType= "Student" > select * from student where tid = #{id} </select> |
3. 将Mapper文件注册到MyBatis-config文件中
4. 测试
1 2 3 4 5 6 7 8 | @Test public void testGetTeacher2(){ SqlSession session = MybatisUtils.getSession(); TeacherMapper mapper = session.getMapper(TeacherMapper. class ); Teacher teacher = mapper.getTeacher2( 1 ); System.out.println(teacher.getName()); System.out.println(teacher.getStudents()); } |
4、小结
- 关联-association
- 集合-collection
- 所以association是用于一对一和多对一,而collection是用于一对多的关系
- JavaType和ofType都是用来指定对象类型的
-
- JavaType是用来指定pojo中属性的类型
- ofType指定的是映射到list集合属性中pojo的类型。
注意说明:
- 保证SQL的可读性,尽量通俗易懂
- 根据实际要求,尽量编写性能更高的SQL语句
- 注意属性名和字段不一致的问题
- 注意一对多和多对一 中:字段和属性对应的问题
- 尽量使用Log4j,通过日志来查看自己的错误
本文来自博客园,作者:腹白,转载请注明原文链接:https://www.cnblogs.com/wyh518/
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?