使用场景:
比如:查询员工信息的同时也要查询出该员工信息的部门信息(同样是一个javaBean)
环境搭建:
Employee类:
package cn.it.mybatis.bean;
import org.apache.ibatis.type.Alias;
@Alias("emp")
public class Employee {
private Integer id;
private String lastName;
private String email;
private String gender;
private Department dept;
public Department getDept() {
return dept;
}
public void setDept(Department dept) {
this.dept = dept;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
@Override
public String toString() {
return "Employee [id=" + id + ", lastName=" + lastName + ", email=" + email + ", gender=" + gender + "]";
}
public Employee(Integer id, String lastName, String email, String gender) {
super();
this.id = id;
this.lastName = lastName;
this.email = email;
this.gender = gender;
}
public Employee() {
super();
// TODO Auto-generated constructor stub
}
}
Department类:
package cn.it.mybatis.bean;
public class Department {
private Integer id;
private String deptName;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getDeptName() {
return deptName;
}
public void setDeptName(String deptName) {
this.deptName = deptName;
}
@Override
public String toString() {
return "Department [id=" + id + ", deptName=" + deptName + "]";
}
}
1.级联属性(属性的属性)封装关联对象
映射文件中的配置:
给dept属性的属性赋值
<result column="did" property="dept.id"/>
<result column="dept_name" property="dept.deptName"/>
<resultMap type="cn.it.mybatis.bean.Employee" id="MyMap2"> <id column="id" property="id"/> <result column="last_name" property="lastName"/> <result column="email" property="email"/> <result column="gender" property="gender"/> <!-- 给级联属性(属性的属性)赋值 --> <result column="did" property="dept.id"/> <result column="dept_name" property="dept.deptName"/> </resultMap> <!-- public Employee getEmpAndDeptById(Integer id); --> <select id="getEmpAndDeptById" resultMap="MyMap2"> SELECT e.id id,e.last_name last_name, e.email email, e.gender gender ,d.id did,d.dept_name dept_name FROM tbl_dept d,tbl_employee e WHERE d.id = e.d_id AND e.id = #{id} </select>
测试代码:
@Test void test10() throws IOException { SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); SqlSession openSession = sqlSessionFactory.openSession(); try { EmployeeMapperPlus mapper = openSession.getMapper(EmployeeMapperPlus.class); Employee employee = mapper.getEmpAndDeptById(2); System.out.println(employee); System.out.println(employee.getDept()); } finally { openSession.close(); } }
查询结果:
两个对象都封装好了
2.使用association 定义关联对象的封装规则
<!-- association:定义关联的单个对象的封装规则 --> <resultMap type="cn.it.mybatis.bean.Employee" id="MyMap3"> <id column="id" property="id"/> <result column="last_name" property="lastName"/> <result column="email" property="email"/> <result column="gender" property="gender"/> <!-- property:指定哪个属性是联合对象 javaType:指定这个属性的类型 --> <association property="dept" javaType="cn.it.mybatis.bean.Department"> <id column="did" property="id"/> <result column="dept_name" property="deptName"/> </association> </resultMap> <!-- public Employee getEmpAndDeptById(Integer id); --> <select id="getEmpAndDeptById" resultMap="MyMap3"> SELECT e.id id,e.last_name last_name, e.email email, e.gender gender ,d.id did,d.dept_name dept_name FROM tbl_dept d,tbl_employee e WHERE d.id = e.d_id AND e.id = #{id} </select>
查询结果:
同样两个对象都封装成功
3. association分步查询
1.DepartmentMapper.xml
<select id="getDeptById" resultType="cn.it.mybatis.bean.Department"> select id,dept_name deptName from tbl_dept where id = #{id} </select>
2.EmployeeMapperPlus.xml
<!-- 使用association进行分步查询 1.先按照员工id查询员工信息 2.根据员工信息中的部门id去部门表查出部门信息 3.将部门设置到员工信息中 --> <resultMap type="cn.it.mybatis.bean.Employee" id="MyMapByStep"> <id column="id" property="id"/> <result column="last_name" property="lastName"/> <result column="email" property="email"/> <result column="gender" property="gender"/> <!-- association定义单个关联对象的封装规则 select:表明当前的属性需要调用select指定的方法查出结果 column:指定将哪一列的值传给这个查询方法 流程:使用select指定的方法(传入column指定的这列参数的值)查出对象,并封装给property指定的属性 --> <association property="dept" select="cn.it.mybatis.dao.DepartmentMapper.getDeptById" column="d_id" > </association> </resultMap> <!-- public Employee getEmpById2(Integer id); --> <select id="getEmpById2" resultMap="MyMapByStep"> select * from tbl_employee where id = #{id} </select>
查询结果:
分步查询可以开启延迟加载(按需加载)
我们在每一次查询员工信息时都会查询出部门信息,
我们希望的是,部门信息时在我们需要的时候在去查询。
实现:分步查询的基础上再全局配置文件中(settings)添加两个配置
推荐:最好是显示的指定每一个配置,即使它是默认值,这是为了防止版本的更新带了的问题
1.lazyLoadingEnabled
2.aggressiveLazyLoading (MyBatis在 3.4.1 及之前的版本默认值为 true)
测试:
只在全局配置文件中配置lazyLoadingEnabled和aggressiveLazyLoading,其他与分步查询一样:
<settings> <setting name="mapUnderscoreToCamelCase" value="true"/> <setting name="lazyLoadingEnabled" value="true"/> <setting name="aggressiveLazyLoading" value="false"/> </settings>
测试代码:
@Test void test10() throws IOException { SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); SqlSession openSession = sqlSessionFactory.openSession(); try { EmployeeMapperPlus mapper = openSession.getMapper(EmployeeMapperPlus.class); Employee employee = mapper.getEmpById2(2); // 只需要员工姓名,不需要部门信息 System.out.println(employee.getLastName()); // 现在需要部门信息 System.out.println(employee.getDept()); } finally { openSession.close(); } }
查询结果: