1.在Mybatis查询中,一条sql查询两个表的数据,可以用到级联属性。例如在员工的属性中加入部门的对象,这样可以用到级联属性来配置:
员工实体类:com.atguigu.mybatis.dao.EmployeeMapper
public class Employee {
private Integer id;
private String lastName;
private String email;
private String gender;
private Department dept;
}
部门实体类:com.atguigu.mybatis.bean.Department
public class Department {
private Integer id;
private String departmentName;
}
配置文件:可以有两种配置方式:级联属性和association定义关联
<!--
1.联合查询:级联属性封装结果集
-->
<resultMap type="com.atguigu.mybatis.bean.Employee" id="MyDifEmp">
<id column="id" property="id"/>
<result column="last_name" property="lastName"/>
<result column="gender" property="gender"/>
<result column="did" property="dept.id"/>
<result column="dept_name" property="dept.departmentName"/>
</resultMap>
<!--
2.使用association定义关联的单个对象的封装规则;
-->
<resultMap type="com.atguigu.mybatis.bean.Employee" id="MyDifEmp2">
<id column="id" property="id"/>
<result column="last_name" property="lastName"/>
<result column="gender" property="gender"/>
<!-- association可以指定联合的javaBean对象
property="dept":指定哪个属性是联合的对象
javaType:指定这个属性对象的类型[不能省略]
-->
<association property="dept" javaType="com.atguigu.mybatis.bean.Department">
<id column="did" property="id"/>
<result column="dept_name" property="departmentName"/>
</association>
</resultMap>
<!-- public Employee getEmpAndDept(Integer id);-->
<select id="getEmpAndDept" resultMap="MyDifEmp">
SELECT e.id id,e.last_name last_name,e.gender gender,e.d_id d_id,
d.id did,d.dept_name dept_name FROM tbl_employee e,tbl_dept d
WHERE e.d_id=d.id AND e.id=#{id}
</select>
这时打印结果:
2.以上查询的sql语句是连接查询,即一条sql查询多个表,这样会导致效率不高,可以将查询改为分步查询和懒加载的方式来处理:即每条sql都只查询一个表,之后在Emp中由association做分步查询,在mybatis的全局配置文件中用setting做懒加载的配置,这样可以达到高效的数据库查询,即当用到哪个表的数据才会执行相关的数据库查询操作,不用就不执行。
具体操作:
部门实体类和员工实体类与上面一致;
mapper的配置:
部门的xml文件中:
<!--public Department getDeptById(Integer id); -->
<select id="getDeptById" resultType="com.atguigu.mybatis.bean.Department">
select id,dept_name departmentName from tbl_dept where id=#{id}
</select>
员工的xml文件中:注意此时使用的是association分步查询,每个mapper.xml文件中只查询mapper对应的实体类再用association进行关联;
<!-- 使用association进行分步查询:
1、先按照员工id查询员工信息
2、根据查询员工信息中的d_id值去部门表查出部门信息
3、部门设置到员工中;
-->
<!-- id last_name email gender d_id -->
<resultMap type="com.atguigu.mybatis.bean.Employee" id="MyEmpByStep">
<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="com.atguigu.mybatis.dao.DepartmentMapper.getDeptById"
column="d_id">
</association>
</resultMap>
<!-- public Employee getEmpByIdStep(Integer id);-->
<select id="getEmpByIdStep" resultMap="MyEmpByStep">
select * from tbl_employee where id=#{id}
</select>
<settings>
<!-- <setting name="mapUnderscoreToCamelCase" value="true"/> -->
<setting name="jdbcTypeForNull" value="NULL"/>
<!--显示的指定每个我们需要更改的配置的值,即使他是默认的。防止版本更新带来的问题 -->
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
<!-- 可以使用延迟加载(懒加载);(按需加载) Employee==>Dept: 我们每次查询Employee对象的时候,都将一起查询出来。 部门信息在我们使用的时候再去查询; 分段查询的基础之上加上两个配置: -->
mybatis.config的全局配置文件:配置懒加载
<settings>
<!--显示的指定每个我们需要更改的配置的值,即使他是默认的。防止版本更新带来的问题 -->
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
效果:
1.开启懒加载模式,只查询员工相关的信息,此时懒加载生效,只发送了一条sql来查询员工信息;
2.开启懒加载,同时查询员工信息和部门信息,则发送两个sql,查询出来两个信息:
3.当要查询部门下的所有员工的信息的时候,就要在部门属性中添加一个list属性,用来存储所有的员工信息:
部门bean:
public class Department {
private Integer id;
private String departmentName;
private List<Employee> emps;
}
员工bean:
public class Employee {
private Integer id;
private String lastName;
private String email;
private String gender;
private Department dept;
}
部门的xml:
<!-- collection:分段查询 column 将哪一列的值作为传递的参数-->
<resultMap type="com.atguigu.mybatis.bean.Department" id="MyDeptStep">
<id column="id" property="id"/>
<id column="dept_name" property="departmentName"/>
<collection property="emps"
select="com.atguigu.mybatis.dao.EmployeeMapperPlus.getEmpsByDeptId"
column="{deptId=id}" fetchType="lazy"></collection>
</resultMap>
<!-- public Department getDeptByIdStep(Integer id); -->
<select id="getDeptByIdStep" resultMap="MyDeptStep">
select id,dept_name from tbl_dept where id=#{id}
</select>
<!-- 扩展:多列的值传递过去:
将多列的值封装map传递;
column="{key1=column1,key2=column2}"
fetchType="lazy":表示使用延迟加载;
- lazy:延迟:用到的时候才发
- eager:立即,马上就发
-->
员工的xml:
<select id="getEmpsByDeptId" resultType="com.atguigu.mybatis.bean.Employee">
select * from tbl_employee where d_id=#{deptId}
</select>
mybatis-condif.xml配置文件中的setting一致;
此时还是懒加载的模式:
即只加载查询相关的信息: