目录
示例
一、处理“多对一”映射关系
1.1、级联查询
1.2、association
1.3、分步查询
二、处理“一对多”映射关系
2.1、collection
2.2、分步查询
示例
例如:员工与部门表
员工:
部门:
解释:
两张表通过dept_id联系起来,员工对部门是一对一关系,部门对员工是一对一关系;
员工实体类:(如下)
public class Emp {
private Integer empId;
private String empName;
private Dept dept;
public Emp(Integer empId, String empName, Dept dept) {
this.empId = empId;
this.empName = empName;
this.dept = dept;
}
@Override
public String toString() {
return "Emp{" +
"empId=" + empId +
", empName='" + empName + '\'' +
", dept=" + dept +
'}';
}
public Dept getDept() {
return dept;
}
public void setDept(Dept dept) {
this.dept = dept;
}
public Emp(Integer empId, String empName) {
this.empId = empId;
this.empName = empName;
}
public Emp() {
}
public Integer getEmpId() {
return empId;
}
public void setEmpId(Integer empId) {
this.empId = empId;
}
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName;
}
}
部门实体类:(如下)
public class Dept {
private Integer deptId;
private String deptName;
private List<Emp> emps;
public Dept(Integer deptId, String deptName) {
this.deptId = deptId;
this.deptName = deptName;
}
public List<Emp> getEmps() {
return emps;
}
@Override
public String toString() {
return "Dept{" +
"deptId=" + deptId +
", deptName='" + deptName + '\'' +
", emps=" + emps +
'}';
}
public void setEmps(List<Emp> emps) {
this.emps = emps;
}
public Integer getDeptId() {
return deptId;
}
public void setDeptId(Integer deptId) {
this.deptId = deptId;
}
public String getDeptName() {
return deptName;
}
public void setDeptName(String deptName) {
this.deptName = deptName;
}
public Dept() {
}
}
一、处理“多对一”映射关系
1.1、级联查询
<resultMap id="EmpAndDeptResultMap" type="Emp">
<id column="emp_id" property="empId"></id>
<result column="emp_name" property="empName"></result>
<result column="dept_id" property="dept.deptId"></result>
<result column="dept_name" property="dept.deptName"></result>
</resultMap>
<select id="getEmpAndDeptByEmpId" resultMap="EmpAndDeptResultMap">
select
emp.*, dept.*
from emp
left join dept
on emp.dept_id = dept.dept_id
where emp.emp_id = #{empId};
</select>
对属性的解释:(这里只解释一次)
id:用来设置主键的映射关系;
result:用来设置普通字段的映射关系;
column:用来设置映射关系的字段名,必须是sql查询出来的某个字段;
property:设置映射关系的属性名,必须是处理的实体类类型中的属性名;
type:用来处理映射关系的实体类类型;
对级联处理的解释:
这里是通过empId来查询员工相应信息以及部门,而查询到的部门结果需要放到一个Dept中(Emp实体类这样设计的),那么级联查询就是通过 dept.deptId 的方式将查询到的deptId放到Dept当中(dept.deptName也是如此);
1.2、association
<resultMap id="EmpAndDeptResultMap" type="Emp">
<id column="emp_id" property="empId"></id>
<result column="emp_name" property="empName"></result>
<association property="dept" javaType="Dept">
<id column="dept_id" property="deptId"></id>
<result column="dept_name" property="deptName"></result>
</association>
</resultMap>
<select id="getEmpAndDeptByEmpId" resultMap="EmpAndDeptResultMap">
select
emp.*, dept.*
from emp
left join dept
on emp.dept_id = dept.dept_id
where emp.emp_id = #{empId};
</select>
对属性的解释:
property:设置需要处理的映射关系的属性的属性名;
javaType:设置要处理的属性的类型;
对association的解释:
和级联处理中的 dept.deptId 达到的效果类似,只是换了一种写法,算是一种模板~
1.3、分步查询
EmpMapper.xml中:(分步查询的第一步)多少步需要根据情况而定
<resultMap id="EmpAndDeptByStepResultMap" type="Emp">
<id column="emp_id" property="empId"></id>
<result column="emp_name" property="empName"></result>
<association property="dept"
select="com.bite.mybatis.mapper.DeptMapper.getEmpAndDeptByStepTwo"
column="dept_id">
</association>
</resultMap>
<select id="getEmpAndDeptByStepOne" resultMap="EmpAndDeptByStepResultMap">
select * from emp where emp_id = #{empId};
</select>
DeptMapper.xml中:(分布查询第二步)
<select id="getEmpAndDeptByStepTwo" resultType="Dept">
select * from dept where dept_id = #{deptId};
</select>
对association中属性的解释:
property:设置需要处理的映射关系的属性的属性名;
select:设置分布查询的sql的唯一标识;
column:将查询出的某个字段作为分布查询的sql的条件;
对分步查询的解释:
具体过程:第一步,通过EmpMapper.xml中的select查询,可以查询出对应的emp信息,而对应的emp信息中就包含了该员工的Dept,然后进行到association中,通过property设置了第二步查询结果的属性名,根据select中的唯一标识,定位并执行第二步查询,最后,查询的结果以column,也就是第一步查询的结果中的某一个属性,为条件进行筛选,最后得出结果;
例如需要查询empId = 2的员工以及部门信息,执行结果如下:
Emp{empId=2, empName='李四', dept=Dept{deptId=2, deptName='B'}}
分布查询优点:
可以实现延迟加载,但需要配置文件(核心配置文件的setting标签的name属性,value属性设置为true标识开启):
lazyLoadingEnabled:延迟加载的全局开关,开启时,所有关联对象都会延迟加载;
aggressiveLazyLoading:开启时,任何方法的调用都会加载该对象的所有属性,否则每个属性按需要加载;
这样就可以实现按需加载,获取的数据是什么,就只会执行对应的sql, 可以通过association和collection中的fetchType属性设置当前分布查询是否使用延迟加载, fetchType = "lazy"(延迟加载)、"eager"(立即加载);
二、处理“一对多”映射关系
2.1、collection
<resultMap id="deptAndEmpResultMap" type="Dept">
<id column="dept_id" property="deptId"></id>
<result column="dept_name" property="deptName"></result>
<collection property="emps" ofType="Emp">
<id column="emp_id" property="empId"></id>
<result column="emp_name" property="empName"></result>
</collection>
</resultMap>
<select id="getDeptAndEmpByDeptId" resultMap="deptAndEmpResultMap">
select
*
from dept
left join emp
on dept.dept_id = emp.dept_id where dept.dept_id = #{deptId};
</select>
对属性的解释:
ofType:设置集合类型的属性中存储的数据的类型;
2.2、分步查询
DeptMapper.xml中:
<resultMap id="deptAndEmpResultMapByStep" type="Dept">
<id column="dept_id" property="deptId"></id>
<result column="dept_name" property="deptName"></result>
<collection property="emps"
select="com.bite.mybatis.mapper.EmpMapper.getDeptAndEmpByStepTwo"
column="dept_id">
</collection>
</resultMap>
<select id="getDeptAndEmpByStepOne" resultMap="deptAndEmpResultMapByStep">
select * from dept where dept_id = #{deptId};
</select>
EmpMapper.xml中:
<select id="getDeptAndEmpByStepTwo" resultType="Emp">
select * from emp where dept_id = #{deptId};
</select>
分步查询的解释和association中是一样的,这里就不过多解释啦~