1,MyBatis的关联映射
MyBatis的关联映射有两种实现方式:
-
- 嵌套查询:通过执行另一个SQL语来返回关联数据(查询两次)
-
- 嵌套结果查询:执行另一个表关联查询SQL,然后将查询结果映射成关联对象(查询一次)
1.1 主键映射
在插入操作时,返回自动递增的主键值
<id column="字段名" jdbcType="对应类型" property="实体类属性名" />
1.1.1 MySql数据库支持自动递增
<insert id="save" parameterType="Dept" useGeneratedKeys="true" keyProperty="deptno">
insert into dept values(#{deptno},#{dname})
</insert>
- 在<insert>标签指定自动递增属性设置后,MyBatis会在插入操作后将自动递增生成的主键值给KeyProperty。
1.1.2 Oracle数据库:
Oracle数据库不支持主键自增,需要采用序列(队列)生成主键值
<insert id="save" parameterType="Dept">
<!-- 先从虚表中查询到下一个值,然后插入表中 -->
<selectKey keyProperty="deptno" resultType="java.lang.Integer">
select dept_sequence.nextval from dual
</selectKey>
insert into dept values(#{deptno},#{dname})
</insert>
- 在<insert>标签中指定设置,MyBatis会在插入操作前,先执行获取主键值的SQL语句,再去执行插入的sql语句。
1.2 一对一映射
主表中的记录在关联表中有且只有一条记录与之对应
- 准备数据:
//创建老师表
create table teacher(
t_id int(4) primary key auto_increment,
t_name varchar(10) not null
);
//创建学生表
create table class(
c_id int(2) primary key auto_increment,
c_name varchar(20),
teacher_id int(4)
);
//外键约束
alter table class add constraint fk_teacher_id
foreign key(teacher_id) references teacher(t_id);
//插入数据
insert into teacher (t_name) values("凯莎");
insert into teacher (t_name) values("卡尔");
----------------------------------------------
insert into class(c_name,teacher_id) values("天使军团",1);
insert into class(c_name,teacher_id) values("饕餮军团",2);
1.2.1 嵌套查询
<!-- 一对一嵌套查询 -->
<select id="findClassByIdOne" parameterType="integer" resultMap="">
select * from class where c_id=#{id}
</select>
<resultMap type="Class" id="classMapperOne">
<id property="id" column="c_id" />
<result property="name" column="c_name" />
<result property="teacherId" column="teacher_id" />
<association property="teacher" column="teacher_id"
javaType="Teacher" select="findTeacher" />
</resultMap>
<select id="findTeacher" parameterType="integer" resultMap="teacherMapperOne">
select * from teacher where t_id=#{id}
</select>
<resultMap type="Teacher" id="teacherMapperOne">
<id property="id" column="t_id" />
<result property="name" column="t_name" />
</resultMap>
1.2.2 嵌套结果查询
<!-- 一对一嵌套结果查询 -->
<select id="findClassByIdTwo" parameterType="integer" resultMap="classMapperTwo">
select c.*,t.* from class c join teacher t on c.teacher_id=t.t_id
where
c_id=#{id}
</select>
<resultMap type="Class" id="classMapperTwo">
<id property="id" column="c_id" />
<result property="name" column="c_name" />
<result property="teacherId" column="teacher_id" />
<association property="teacher" column="teacher_id"
javaType="Teacher">
<id property="id" column="t_id" />
<result property="name" column="t_name" />
</association>
</resultMap>
1.3 一对多映射
主表中的一条记录在关联表中有多条记录(一对多);
例如:一个班级对应多个学生
1.3.1 嵌套查询
<!-- 一对多嵌套查询 -->
<select id="findDeptByDeptnoOne" parameterType="integer"
resultMap="deptMapOne">
select * from dept where deptno=#{deptno}
</select>
<resultMap type="Dept" id="deptMapOne">
<id property="deptno" column="deptno" />
<collection property="emps" column="deptno" javaType="java.util.ArrayList"
ofType="Emp" select="findEmps" />
</resultMap>
<select id="findEmps" parameterType="integer" resultType="Emp">
select
* from emp where deptno=#{deptno}
</select>
1.3.2 嵌套结果查询
在嵌套结果查询中,即使实体类属性名与字段名一致,也不会进行自动映射。
- 解决:
- 增加autoMapping=“true”属性并设置值为true;
<collection property="emps" column="deptno" javaType="java.util.ArrayList" ofType="Emp" autoMapping="true"/>
- 自己手动去关联映射
<id property="deptno" column="deptno"/>
<result property="dname" column="dname"/>
...
示例:
<!-- mapper.xml配置 -->
<!-- 一对多嵌套结果查询 -->
<select id="findDeptByDeptnoTwo" parameterType="integer" resultMap="deptMapperTwo">
select d.* ,e.*
from dept d join emp e on d.deptno=e.deptno where
d.deptno=#{deptno}
</select>
<resultMap type="Dept" id="deptMapperTwo">
<id property="deptno" column="deptno"/>
<result property="dname" column="dname"/>
<collection property="emps" column="deptno" javaType="java.util.ArrayList" ofType="Emp" autoMapping="true"/>
</resultMap>
1.4 多对一映射
表中多条记录对应关联表中一条记录(相当于一对多的反过来),将一对多关联中的主表与关联表交换位置后,描述此时的关系即为多对一。
1.4.1 嵌套查询
<!-- 多对一嵌套查询 -->
<select id="findEmpByEmpnoOne" parameterType="integer"
resultMap="empMapOne">
select * from emp where empno=#{empno}
</select>
<resultMap type="Emp" id="empMapOne">
<result property="deptno" column="deptno" />
<association property="dept" column="deptno" javaType="Dept"
select="findDept" />
</resultMap>
<select id="findDept" parameterType="integer" resultType="Dept">
select
* from dept where deptno=#{deptno}
</select>
1.4.2 嵌套结果查询
<!-- 多对一嵌套结果查询 -->
<select id="findEmpByEmpnoTwo" parameterType="integer"
resultMap="empMapTwo">
select e.*,d.* from emp e inner join dept d on e.deptno=d.deptno
where e.empno=#{empno}
</select>
<resultMap type="Emp" id="empMapTwo" autoMapping="true">
<result property="deptno" column="deptno" />
<association property="dept" column="deptno" javaType="Dept"
autoMapping="true"/>
</resultMap>
1.5 多对多映射
- 主表中的一条记录在关联表中有多条记录与之关联。
- 关联表中的一条记录在主表中有多条记录与之关联。
- 存在一张中间表来描述多对多的关联关系。
例如:- 一个学生可以选择多个课程
- 一门课程可以被多个学生选择
- 准备数据:
//学生表
create table students(
s_id int(4) primary key auto_increment,
s_name varchar(20) not null
);
//课程表
create table course(
c_id int(4) primary key auto_increment,
c_name varchar(20) not null
);
//中间表描述学生与课程的关系
create table student_course(
student_id int(4),
course_id int(4)
);
//插入数据
insert into students(s_name) values("彦"),("炙心"),("葛小伦"),("赵信");
insert into course(c_name) values("银河之力"),("天使审判"),("绝影神枪"),("银翼之刃"),("雄心"),("黑甲"),("太阳之力");
insert into student_course values(1,4),(1,2),(2,1),(3,1),(3,5),(4,3),(1,7),(2,6),(3,6),(4,6);
1.5.1 嵌套查询
<!-- 多对多嵌套查询 -->
<select id="findByStudentIdOne" parameterType="integer"
resultMap="stuMapOne">
select * from students where s_id=#{id}
</select>
<resultMap type="Student" id="stuMapOne">
<id column="s_id" property="id" />
<result column="s_name" property="name" />
<collection property="courses" column="s_id" javaType="java.util.ArrayList"
ofType="Course" select="findCourse" />
</resultMap>
<select id="findCourse" parameterType="integer" resultMap="courseMap">
select c.*
from student_course sc join course c
on sc.course_id=c.c_id
where sc.student_id=#{id}
</select>
<resultMap type="Course" id="courseMap">
<id property="id" column="c_id" />
<result property="name" column="c_name" />
</resultMap>
1.5.2 嵌套结果查询
<!-- 嵌套结果查询 -->
<select id="findByStudentIdTwo" parameterType="integer"
resultMap="stuMapTwo">
select st.* ,c.*
from students st join student_course sc on
st.s_id=sc.student_id join
course c on sc.course_id=c.c_id where
st.s_id=#{id}
</select>
<resultMap type="Student" id="stuMapTwo">
<id property="id" column="s_id" />
<result property="name" column="s_name" />
<collection property="courses" column="s_id" javaType="java.util.ArrayList"
ofType="Course">
<id property="id" column="c_id" />
<result property="name" column="c_name" />
</collection>
</resultMap>