当前位置: 首页 > 图灵资讯 > 技术篇> 一对多和多对一处理

一对多和多对一处理

来源:图灵教育
时间:2023-06-17 13:48:50

1 多对一处理

多对一的理解

班主任与学生在学校的管理关系:

  • 班主任管理多个外国学生 。也就是说,从班主任的角度来看,一个班主任与多个学生有关(1):N)
  • 一个学生只能有一个班来管理他。也就是说,从学生的角度来看:一个学生和一个老师有关!(1:1)
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)
  •  
  • 对于老师来说,这是一个一对多的现象,也就是说,有一群学生(聚会)来自一个老师!
  •  
2.2 实体类编写
@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.2 多关系数据库表3.2.1 学生表3.2.2 课程表3.2.3 中间表

也叫选课表或成绩单。

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,通过日志检查自己的错误

上一篇:

JAVA Aop与Ioc

下一篇:

Spring依赖查找