首先我们先创建两个表和pojo用来演示多表查询,如下:
用户表:t_emp表,其中emp_id为自增主键。
t_emp对应的pojo:Employee
public class Employee {
private Integer empId;
private String empName;
private Integer age;
private String gender;
private Dept dept;
public Employee(Integer empId, String empName, Integer age, String gender, Dept dept) {
this.empId = empId;
this.empName = empName;
this.age = age;
this.gender = gender;
this.dept = dept;
}
public Employee() {
}
//Setter and Getter方法必须要有,这里不在展示
@Override
public String toString() {
return "Employee{" +
"empId=" + empId +
", empName='" + empName + '\'' +
", age=" + age +
", gender='" + gender + '\'' +
", dept=" + dept +
'}';
}
}
部门表:t_dept,dept_id为主键
public class Dept {
private Integer deptId;
private String deptName;
private Collection<Employee> employees;
public Dept(Integer deptId, String deptName) {
this.deptId = deptId;
this.deptName = deptName;
}
public Dept() {
}
//Setter and Getter方法必须要有,这里不在展示
@Override
public String toString() {
return "Dept{" +
"deptId=" + deptId +
", deptName='" + deptName + '\'' +
", employees=" + employees +
'}';
}
}
在核心配置文件中的Setting的配置
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
settings>
多对一查询:第一张表中的多条记录可能对应第二张表中的一条记录,并且在第一张表对应的类中存在第二张表对应类的实例变量。对应到例子中,员工表中,不同的员工肯属于同一个部门,员工表中有部门类型的实例。这里提供三种查询方式。
在EmployeeMapper.xml中:
<resultMap id="empAndDeptResultMapOne" type="pojo.Employee">
<id column="emp_id" property="empId"/>
<result column="emp_name" property="empName"/>
<result column="age" property="age"/>
<result column="gender" property="gender"/>
<result column="dept_id" property="dept.deptId"/>
<result column="dept_name" property="dept.deptName"/>
resultMap>
在EmployeeMapper.xml中:
<resultMap id="empAndDeptResultMapTwo" type="pojo.Employee">
<id column="emp_id" property="empId"/>
<result column="emp_name" property="empName">/result>
<result column="age" property="age"/>
<result column="gender" property="gender"/>
<association property="dept" javaType="pojo.Dept">
<id column="dept_id" property="deptId"/>
<result column="dept_name" property="deptName"/>
association>
resultMap>
在DeptMapper中:
<select id="getDeptById" resultType="pojo.Dept">
select *from t_dept where dept_id = #{dept_id};
select>
在EmployeeMapper.xml中:
<resultMap id="empAndDeptResultMapByStep" type="pojo.Employee">
<id column="emp_id" property="empId"/>
<result column="emp_name" property="empName"/>
<result column="age" property="age"/>
<result column="gender" property="gender"/>
<association property="dept"
select="mapper.DeptMapper.getDeptById"
column="dept_id"/>
resultMap>
<select id="getDeptById" resultType="pojo.Dept">
select *from t_dept where dept_id = #{deptId};
select>
一对多查询:第一张表中的一条记录对应第二张表中的多条记录,并且在第一张表对应类中有第二张表对应类中的实例集合属性。对应到例子当,一个部门可能会有多个员工,相应的部门表对应类中有List集合类型的属性。这里提供两种查询方式。
在DeptMapper中:
<resultMap id="deptAndEmpResultMap" type="pojo.Dept">
<id column="dept_id" property="deptId"/>
<result column="dept_name" property="deptName"/>
<collection property="employees" ofType="pojo.Employee">
<id column="emp_id" property="empId"/>
<result column="emp_name" property="empName"/>
<result column="age" property="age"/>
<result column="gender" property="gender"/>
collection>
resultMap>
在EmployeeMapper.xml中:
<select id="getEmpByDept" resultType="pojo.Employee">
select *from t_emp where dept_id = #{dept_id};
select>
在DeptMapper中:
<resultMap id="deptAndEmpByStepResultMap" type="pojo.Dept">
<id column="dept_id" property="deptId"/>
<result column="dept_name" property="deptName"/>
<collection property="employees" ofType="Employee" select="mapper.EmpMapper.getEmpByDept" column="dept_id"/>
resultMap>
<select id="getEmpByDept" resultType="pojo.Employee">
select *from t_emp where dept_id = #{dept_id};
select>
在mybatis的核心配置文件当中可以配置这两种属性。
<settings>
<setting name="lazyLoadingEnabled" value="false"/>
<setting name="aggressiveLazyLoading" value="false"/>
settings>
按需加载:按需加载又称懒加载,在需要时才会去加载。我们以多对一的分步查询为例。
@Test
public void testGetAllEmpAndDeptByStep(){
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
List<Employee> employeeList = empMapper.getAllEmpAndDeptByStep();
employeeList.forEach((Employee employee) ->{
System.out.println(employee.getEmpName());
});
}
我们在设置属性lazyLoadingEnabled之前:
编译后的日志记录如下:
尽管我们只需要emp_name,仅通过select * from t_emp就可以将所需数据查出来,但是我们还是进行了两步查询。
我们将属性lazyLoadingEnabled设置为true,aggressiveLazyLoading默认为false,所以此时是按需加载。
编译后的日志记录如下:
因为需要的对象仅通过select * from t_emp就能得出,所以只会进行这一次查询。
此时我们再将属性aggressiveLazyLoading设置为true,编译后的日志记录如下:
此时不在是按需加载,而是完整加载。
在按需加载时,我们可以在collection标签或者是association标签中设置的fetchType属性设置当前的分步查询是否使用延迟加载, fetchType="lazy(延迟加载)|eager(立即加载)