【学习笔记】多对一和一对多
概念:
以老师和学生为例
多对一:多个学生对应一个老师,关键词【关联】 多个学生关联一个老师
一对多:一个老师对应多个学生,关键词【集合】
设计环境
创建老师表和学生表,学生表中有老师表的id作为外键
在java模型中 teacher 还是和之前一样两个属性(id,name)都不是对象,而student中的tid是Teacher对象
public class Student {
private int id;
private String name;
private Teacher teacher;
}
多对一需求
查询所有学生和其对应的老师
之前可以通过sql去实现,子查询和联表查询
子查询:
select s.id,s.name,t.name from student s, teacher t where s.tid=(
select id from teacher where tid = 1
)
联表查询:
select s.id,s.name,t.name from student s,teacher t where s.tid = t.id
现在我们在mybatis中,通过xml 标签去实现,就不像之前那么简单,因为student 的数据库的列tid与Student实体类的Teacher类不对应,所以要使用结果集映射 resultMap
resultMap 中的 result标签不能用于对象和数据库列的映射,所以我们要使用 association
有两种方式:
-
按照查询 嵌套处理
这种方式就像子查询,先在student表中查出所有的信息,使用结果集映射resultMap
用association 标签 将 Teacher类与数据库中的列tid映射,并且在嵌套一层查询(就是从association 标签中 再写一个 select属性 这个 select属性 绑定 查询teacher表的 select标签)
在查询teacher标签的中通过tid去查
<select id="getStudent1" resultMap="StudentTeacher"> select * from jdbcstudy.student </select> <resultMap id="StudentTeacher" type="Student"> <result property="id" column="id"/> <result property="name" column="name"/> <association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/> </resultMap> <select id="getTeacher" resultType="Teacher"> select * from jdbcstudy.teacher where id = #{tid} </select>
-
按照结果 嵌套处理
这种方式就像联表查询,在student的select标签中写入完整的联表查询sql语句,并且给每个字段取一个别名,然后绑定一个resultMap,其中的result标签是将sql中的别名与student实体类的属性绑定,resultMap中的association标签 的属性只写 teacher对象的名称和javaType(Teacher实体类)标签的内容是将Teacher的属性与sql的别名绑定
<select id="getStudent2" resultMap="StudentTeacher2"> select s.id sid,s.name sname,t.id tid,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 column="tname" property="name"/> <result column="tid" property="id"/> </association> </resultMap>
一对多
一对多是集合
查询某个老师的以及该老师对应的学生
与多对一大体相同,不同的是实体类中,学生类的属性不是对象,老师类有学生类的集合
public class Student {
private int id;
private String name;
private int tid;
}
public class Teacher {
private int id;
private String name;
private List<Student> students;
}
还是有两种方式
-
按照结果嵌套处理
<select id="getTeacher1" resultMap="TeacherStudent"> select t.id tid,t.name tname,s.id sid,s.name sname, s.tid stid from teacher t,student s where t.id = #{id} </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="stid"/> </collection> </resultMap>
与之前不同的地方:
-
因为是一对多,所以用的标签是collection
-
collection的属性从javaType变成 ofType
-
javaType是实体类中属性的类型
-
ofType是实体类中集合的泛型类型
-
-
-
按照查询嵌套处理
<select id="getTeacher2" resultMap="TeacherStudent2"> select * from teacher where id = #{id} </select> <resultMap id="TeacherStudent2" type="Teacher"> <result property="id" column="id"/> <result property="name" column="name"/> <collection property="students" javaType="ArrayList" ofType="Student" column="id" select="getStudent"/> </resultMap> <select id="getStudent" resultType="Student"> select * from student where tid = #{id} </select>
与之前不同的地方:
-
同样标签使用的是collection
-