1 多对一处理
多对一的理解
班主任与学生在学校的管理关系:
- 班主任管理多个外国学生 。也就是说,从班主任的角度来看,一个班主任与多个学生有关(1):N)
- 一个学生只能有一个班来管理他。也就是说,从学生的角度来看:一个学生和一个老师有关!(1:1)
CREATE TABLE `teacher` (`id` INT(10) NOT NULL,`name` VARCHAR(30) DEFAULT NULL,PRIMARY KEY (`id`)) ENGINE=INNODB DEFAULT CHARSET=utf8INSERT INTO teacher(`id`, `name`) VALUES (1, "张老师";INSERT INTO teacher(`id`, `name`) VALUES (2, "王老师";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=utf8INSERT 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');INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('6', '小强', '2');INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('7', '小刘', '2');INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('8', '小明', '2');
1.2 1.2构建测试环境.1 Lombok插件1.2安装IDEA.2 引入Maven依赖
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok --><dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.16.10</version></dependency>
1.2.3 在代码中添加注释
@Data //GET,SET,ToString,有参,public无参构造 class Teacher { private int id; private String name;}@Datapublic class Student { private int id; private String name; //多个学生可以是同一个老师,即多对一 private Teacher teacher;}
1.2.4 编写实体类对应的Mapper接口 【两个】
- 不管有没有需要,都要写下来,以备以后的需要!
public interface StudentMapper {}public interface TeacherMapper {}
1.2.5 编写Mapper接口对应的编写 mapper.xml配置文件 【两个】
- 不管有没有需要,都要写下来,以备以后的需要!
<?xml versinotallow="1.0" encoding="UTF-8" ?><!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "https://www.tulingxueyuan.cn/d/file/p/20230617/w4flcxavv5j.dtd"><mapper namespace="com.kuang.mapper.StudentMapper"></mapper>
<?xml versinotallow="1.0" encoding="UTF-8" ?><!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "https://www.tulingxueyuan.cn/d/file/p/20230617/w4flcxavv5j.dtd"><mapper namespace="com.kuang.mapper.TeacherMapper"> <!--<select id="getTeacher" resultType="com.dzxx.jsj.pojo.Teacher">--> <!--<select id="getTeacher" resultType="com.dzxx.jsj.pojo.Teacher">--> <!--select * from teacher where id = #{id} --> <!--</select> --></mapper>
1.3 1.33按查询嵌套处理.1 增加Studentmaper接口的方法
///获取所有学生和相应老师的信息public List<Student> getStudents();
1.3.2 编制相应的Mapper文件
<?xml versinotallow="1.0" encoding="UTF-8" ?><!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "https://www.tulingxueyuan.cn/d/file/p/20230617/w4flcxavv5j.dtd"><mapper namespace="com.kuang.mapper.StudentMapper"> <!-- 需求:获取所有学生及相应教师的信息 思路: 1. 获取所有学生的信息 2. 根据获得的学生信息的教师ID->获取老师的信息 3. 思考问题,这样学生的结果应该集中在老师身上。如何处理?我们通常在数据库中使用相关查询? (1). 结果集映射:StudentTeacher (2). Studenteacher结果集的类型是 Student (3). 教师在学生中的属性是teacher,对应于student数据库中的tid。 多个学生关联一个老师=> 多对一 , 一对一 (4). 查看官网找到:association 复杂类型的关联;用它来处理关联查询 --> <!--方式1: TeacherMaper不需要.xml写映射 --><!--方式1: TeacherMaper不需要.xml写映射 --><!--<resultMap id="StudentTeacher" type="Student">--><!-- <id property="id" column="id"/>--><!-- <result property="name" column="name"/>--><!-- <association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/>--><!-- <association property="teacher" column="{id=tid,name=tid}" javaType="Teacher" select="getTeacher"/>--><!--</resultMap>--><!-- <select id="getTeacher" resultType="teacher">--><!-- select * from teacher where id = #{id}--><!-- </select>--><!-- <select id="getStudents" resultMap="StudentTeacher">--><!-- select * from student--><!-- </select>--><!--===================================--> <!--方式2:TeacherMaper需要.xml 中编写SQL映射 --> <resultMap id="StudentTeacher" type="Student"> <id property="id" column="id"/> <result property="name" column="name"/> <association property="teacher" column="tid" javaType="Teacher" select="com.dzxx.jsj.mapper.TeacherMapper.getTeacher"/> </resultMap> <select id="getStudents" resultMap="StudentTeacher"> select * from student </select></mapper>
1.3.3 在Mybatis配置文件中注册Maper!1.3.4 注意点说明
column={prop1=col1,prop2=col2}
<resultMap id="StudentTeacher" type="Student"> <!--association关联属性 property属性名称 javatype属性类型 column在多方表中的排名--> <association property="teacher" column="{id=tid,name=tid}" javaType="Teacher" select="getTeacher"/></resultMap><!--这里传递的id只有一个属性,下面可以写任何值 column多参数配置association: column={property1=column1,property2=column2} 其实是键值对的形式,property1是传递给下一个sql的取值名称,column1是片段一中sql查询的字段名。--><select id="getTeacher" resultType="teacher"> select * from teacher where id = #{id} and name = #{name}</select>
1.3.5 测试
@Testpublic void testGetStudents(){ SqlSession session = MybatisUtils.getSession(); StudentMapper mapper = session.getMapper(StudentMapper.class); List<Student> students = mapper.getStudents(); for (Student student : students){ System.out.println( “学生名:”+ student.getName() +"\t老师:"+student.getTeacher().getName()); }}
1.4 按结果进行嵌套处理
除上述方法外,还有其他想法吗?
我们也可以根据结果进行嵌套处理;方法3
1.4.1 编写接口方法
public List<Student> getstudents2();
1.4.2 编制相应的mapper文件
<!--根据查询结果嵌套处理思路: 1. 直接查询结果,并对结果集进行映射--><!--===========方式3:============--> <resultMap id=“Studenteacher2” type="Student"> <id property="id" column="id"/> <result property="name" column="name"/> <association property="teacher" javaType="Teacher"> <id property="tid" column="id"/> <result property="name" column="name"/> </association> </resultMap> <select id="getStudents" resultMap=“Studenteacher2”> select student.*,t.name from student,teacher as t where student.tid = t.id </select>
1.4.3 将mapper1.4.4注入mybatis-config文件.4 测试
@Testpublic void testgetstudents2(){ SqlSession session = MybatisUtils.getSession(); StudentMapper mapper = session.getMapper(StudentMapper.class); List<Student> students = mapper.getstudents2(); for (Student student : students){ System.out.println( “学生名:”+ student.getName() +"\t老师:"+student.getTeacher().getName()); }}
小结
按查询进行嵌套处理就像SQL中的子查询一样
按结果进行嵌套处理就像SQL中的联表查询一样
一对多处理
2 一对多处理2.1 一对多的理解:- 班主任与学生在学校的管理关系:
- 班主任管理多个外国学生 。也就是说,从班主任的角度来看,一个班主任与多个学生有关(1):N)
- 一个学生只能有一个班来管理他。也就是说,从学生的角度来看:一个学生和一个老师有关!(1:1)
- 对于老师来说,这是一个一对多的现象,也就是说,有一群学生(聚会)来自一个老师!
@Data@ToStringpublic class Student { private Integer sno; private String sname; private Integer age; private Integer tid; //一个学生对应一个老师}
@Data //GET,SET,ToString,有参,public无参构造 class Teacher { private int tid; private String name; private List<Student> studentList; ///老师对应 多个学生}
2.3 按结果进行嵌套处理
1、Teachermaper接口编写方法
public interface TeacherMapper { public Teacher getTeacherById(int tid);}
2、编写接口对应的Mapper配置文件
<?xml versinotallow="1.0" encoding="UTF-8" ?><!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "https://www.tulingxueyuan.cn/d/file/p/20230617/w4flcxavv5j.dtd" ><mapper namespace="com.dzxx.jsj.mapper.TeacherMapper"> <resultMap id="teacherResultMap" type="com.dzxx.jsj.pojo.Teacher"> <collection property="studentList" ofType="com.dzxx.jsj.pojo.Student" column="tid" select="findStudentByTid"> </collection> </resultMap> <!--根据老师号查询--> <select id="getTeacherById" parameterType="int" resultMap="teacherResultMap"> select tid,name from teacher where tid = #{tid} </select> <!--根据学号查询--> <select id="findStudentByTid" parameterType="int" resultType="student"> select sno,sname,age,tid from student where tid = #{tid} </select></mapper>
3、在MyBatis-config文件中注册Mapper文件
<!-- mapping文件路径配置 --> <mappers> <package name="com.dzxx.jsj.mapper"/> </mappers>
4、测试
@Test public void testGetTeacherById(){ TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class); Teacher teacher = mapper.getTeacherById(2); System.out.println(teacher.toString()); }
3 多对多处理3.1 一对多的理解:
- 在学校,学生与课程之间的选课关系:
- 一班学生可以选修多门课程。
- 多个学生可以选修一门课程。
- 这就形成了多对多的关系!数据库中需要一个中门表来表示这种多对多的关系
也叫选课表或成绩单。
3.3 实体类编写
@Data@ToStringpublic class Student { private Integer sno; private String sname; private Integer age; private Integer tid; private List<Course> courseList; //学生会选修多门课程
@Data@ToStringpublic class Course { private Integer cno; private String cname;}
@Data@ToStringpublic class Sc { private Integer id; private Integer sno; private Integer cno; private Double score;}
3.4 按结果进行嵌套处理
1、Studentmaper接口编写方法
public interface StudentMapper { ///获取所有学生和相应老师的信息 public List<Student> findStudentBySno(int sno); public List<Student> findAllStudents();}
2、编写接口对应的Mapper配置文件
<?xml versinotallow="1.0" encoding="UTF-8" ?><!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "https://www.tulingxueyuan.cn/d/file/p/20230617/w4flcxavv5j.dtd" ><mapper namespace="com.dzxx.jsj.mapper.StudentMapper"> <resultMap id="courseResultMap" type="com.dzxx.jsj.pojo.Course"> <id column="cno" property="cno"/> <result column="cname" property="cname"/> </resultMap> <resultMap id="studentResultMap" type="com.dzxx.jsj.pojo.Student" extends="courseResultMap"><!-- <id property="sno" column="sno"></id>--><!-- <id property="sno" column="sno"></id>--><!-- <result property="sname" column="sname"/>--><!-- <result property="age" column="age"/>--><!-- <result property="tid" column="tid"/>--> <collection property="courseList" ofType="com.dzxx.jsj.pojo.Course" column="sno" select="findCourseByCno"> </collection> </resultMap> <!--根据学号查询--> <select id="findStudentBySno" parameterType="int" resultMap="studentResultMap"> select sno,sname,age,tid from student where sno = #{sno} </select> <select id="findCourseByCno" parameterType="int" resultType="com.dzxx.jsj.pojo.Course"> select cno,cname from course where cno in(select cno from sc where sno = #{sno}) </select> <!--根据学号查询--> <select id="findAllStudents" parameterType="int" resultMap="studentResultMap"> select sno,sname,age,tid from student </select></mapper>
3、在MyBatis-config文件中注册Mapper文件
<!-- mapping文件路径配置 --> <mappers> <package name="com.dzxx.jsj.mapper"/> </mappers>
4、测试
@Test public void testFindStudentBySno(){ StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); List<Student> students = mapper.findStudentBySno(2); for (Student student : students){ System.out.println( "学生:"+ student.toString()); ; } } @Test public void testFindAllStudents(){ StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); List<Student> students = mapper.findAllStudents(); for (Student student : students){ System.out.println( "学生:"+ student.toString()); ; } }
4 小结
1、关联-association
2、集合-collection
3、因此,association用于一对一和多对一,而colection用于一对多关系
4、Javatype和oftype用于指定对象类型
- Javatype用于指定pojo中属性的类型
- oftype指定了映射到list集合属性中pojo的类型。
注意说明:
1、保证SQL的可读性,尽量通俗易懂
2、根据实际要求,尽量编写性能较高的SQL句子
3、注意属性名与字段不一致的问题
4、注意一对多和多对一 中间:字段与属性对应的问题
5、尽量使用log4j,通过日志检查自己的错误
