对象关系分类
泛化关系,实现关系,依赖关系,关联关系,聚合关系,组合关系
使用最多的就是关联关系
单向多对一保存的关系
例子:保存一个部门和两个员工,两个员工属于这个部门
所以需要在员工里面有一个部门的属性
创建员工和部门两个实体类
public class Employee {
private Long id;
private String name;
//关联属性
private Dept dept;
}
此时部门表和员工表都需要同时进行插入数据
将部门的id同时插入到员工表里面,此时只需要给附表添加取主键的属性
deptMapper.xml
<!--
useGeneratadKeys="true":获取数据保存数据的主键值
keyProperty="id": 列名
-->
<insert id="insert" useGeneratadKeys="true" keyProperty="id">
insert into dept values(#{name})
</insert>
EmployeeMapper.xml,可以使用里面的dept属性获取部门的id
<!--主表不用给抽主键的值-->
<insert id="insert" parameterType="cn.wolfcode.mapper.EmployeeMapper" >
insert into employee (name,dept_id) values(#{name},#{dept.dept_id})
</insert>
在测试类里面需要先保存部门才能在保存员工,这样才有部门的id值可以进行返回,穿进去的是一个员工对象
/**
* 添加员工并且使用从表添加部门编号
*/
@Test
public void insert(){
SqlSession session = MybatisUtil.getSession();
DeptMapper deptMapper = session.getMapper(DeptMapper.class);
Dept dept = new Dept();
dept.setDept_name("研发部");
//先保存部门
deptMapper.insert(dept);//这里会返回部门的id,可以使用dept.getid()获取部门的id
EmployeeMapper employeeMapper = session.getMapper(EmployeeMapper.class);
Employee employee1 = new Employee();
employee1.setName("小小");
employee1.setDept(dept);
Employee employee2 = new Employee();
employee2.setName("灰灰");
employee2.setDept(dept);
//保存员工
employeeMapper.insert(employee1);
employeeMapper.insert(employee2);
session.commit();
session.close();
单向多对一额外sql查询使用的resultMap标签
方式1,直接使用属性的里面的值,重新给查询结果添加别名
<resultMap id="emp_resultMap" type="cn.wolfcode.domain.Emp">
<id column="id" property="id"></id>
<result column="name" property="name"></result>
<result column="did" property="dept.id"></result>
<result column="dname" property="dept.name"></result>
</resultMap>
<select id="selectById" resultType="cn.wolfcode.domain.Emp" resultMap="emp_resultMap">
select e.id,e.`name`,d.id did,d.`name` dname
from employee e
join department d
on e.dept_id=d.id
where e.id=#{id}
</select>
方式2
使用多对一查询的时候需要使用sql中的resultMap标签
例子:查询员工及员工的部门
部门表不需要要进行任何处理
<resultMap id="selectAll" type="cn.wolfcode.domain.Employee">
<id column="id" property="id"></id>
<result column="name" property="name"></result>
<association property="dept" javaType="cn.wolfcode.domain.Dept" >
<id column="dept_id" property="dept_id"></id>
<result column="dept_name" property="dept_name"></result>
</association>
</resultMap>
<select id="select" resultType="cn.wolfcode.domain.Employee" resultMap="selectAll">
select name,employee.dept_id ,dept.dept_name from employee join dept on employee.dept_id=dept.dept_id
</select>
resultMap标签及其作用
作用:用于自定义实体类与数据库查询结果集之间的映射关系,可以使用该标签实现查询返回的多个列
参数含义:
<resultMap id="selectAll" type="cn.wolfcode.domain.Employee">
<id column="id" property="id"></id>
<result column="name" property="name"></result>
id:给这个resulMap明一个别名
type:这个resoutMap的映射类型
<id column="id" property="id"></id>
表示主键字段或者属性在数据库中的列名
colum:查询出来的列名的名字,可以重新命名
property:主键对应的实体类属性名
<result column="name" property="name"></result>
表示普通字段或者属性在数据库中的列名
colum:查询出来的列名的名字,可以重新命名
property:实体类的普通属性名
association标签
他是在resultMap标签之中的,一个表查一个的时候使用association
<association property="dept" javaType="cn.wolfcode.domain.Dept" >
<id column="dept_id" property="dept_id"></id>
<result column="dept_name" property="dept_name"></result>
</association>
在单向多对一查询使用,即一个属性通过另一个sql查询的实体类对象得到
property:指定当前属性在这个实体类中对应的那一个属性名,一般这个属性是由另一个实体类定义而来
javaType:定义这个属性名的实体类的全限定名
里面的,标签就对应这个表名的列名和这个实体类的属性
collection标签
他是在resultMap标签之中的,求list集合的时候使用collection
<resultMap id="stu_teacher_resultMap" type="cn.wolfcode.domain.Stu">
<!--id标签表示的主键-->
<id property="id" column="id"></id>
<result property="name" column="name"></result>
<!--
property:stu中的属性
ofType:teachers本身的类型
javaType:teachers在stu中的类型
-->
<collection property="teachers" javaType="list" ofType="cn.wolfcode.domain.Teacher">
<id property="id" column="tid"></id>
<result property="name" column="tname"></result>
</collection>
</resultMap>
<!--
使用resoutMap进行查询
-->
<select id="get" resultType="cn.wolfcode.domain.Stu" resultMap="stu_teacher_resultMap">
select stu.*,teacher.id tid,teacher.name tname
from stu
join stu_teacher
on stu.id=stu_teacher.sid
join teacher
on stu_teacher.tid=teacher.id
where stu.id=#{id}
</select>
在一对多或者多对多查询的时候使用,一个属性有多个关联的是实体类对象
property:指定当前关联的实体对象属性
javaType:定义这个属性名的实体类的全限定名
oftype:指定集合元素的类型,使用这个自定义属性名的全限定名
select:指定执行sql语句的id(就是其他xxxMapper中的接口中的方法名,和这个属性相互对应)
<resultMap id="stu_resoutMap" type="cn.wolfcode.domain.Stu">
<id property="id" column="id"></id>
<result property="name" column="name"></result>
<!--这里的select关联到teacher上的查询条件,将这个id传到另一个mapper-->
<collection column="id" property="teachers" select="cn.wolfcode.mapper.TeacherMapper.queryByStudentid" />
</resultMap>
column="id"
:指定了当前对象在 SQL 语句查询结果集中的列名,这个列名用于匹配关联对象的外键
property="teachers"
:指定了当前对象(即父对象)中集合类型属性的名称,也就是要将关联对象赋值给哪个属性。
select:这里使用了另一个 Mapper 接口中定义的 ID 为 “queryByStudentid” 的查询方法。
什么是n+1问题及解决办法
出现的原因:若某个查询条件反回了多个结果,并且这些结果又对应了另外一个查询条件的多行结果,此时就会发生n+1次查询的情况
**解决办法:**一般使用关联查询,将多张表进行联合起来进行查询,避免单独查询利用标签和