提示:这是MyBatis的第二篇,没看第一篇可以先看第一篇:MyBatis复习笔记整理
association
标签可以指定联合封装的JavaBean
对象,
property
指定封装到哪个属性,
javaType
指定这个属性的对象类型(全类名)
先配置resultMap
标签,dept
属性使用association
标签指定:
<resultMap type="com.atguigu.bean.Employee" id="MyEmpWithDept2">
<id column="id" property="id"/>
<result column="last_name" property="lastName"/>
<result column="gender" property="gender"/>
<result column="email" property="email"/>
<association property="dept" javaType="com.atguigu.bean.Department">
<id column="dept_id" property="id"/>
<result column="dept_name" property="deptName"/>
association>
resultMap>
再写select
标签:
<select id="selectWithDeptById2" resultMap="MyEmpWithDept2">
select a.*,b.dept_name
from tbl_employee a
left join tbl_dept b
on a.dept_id = b.id
where a.id = #{id}
select>
这个association
标签感觉跟之前用的#{dept.deptName}
区别不是很大,甚至比之前要麻烦。
先查询员工信息,然后用员工信息里的部门号再查询一次部门表。
先把DepartmentMapper接口和xml写好:
public interface DepartmentMapper {
public Department selectDeptById(Integer id);
}
<mapper namespace="com.atguigu.dao.DepartmentMapper">
<select id="selectDeptById" resultType="com.atguigu.bean.Department">
select * from tbl_dept
where id = #{id}
select>
mapper>
在EmployeeMapper
接口中新增分步查询的方法selectEmpWithDeptByStep
:
public interface EmployeeMapperPlus {
public Employee selectById(Integer id);
public Employee selectWithDeptById(Integer id);
public Employee selectWithDeptById2(Integer id);
public Employee selectEmpWithDeptByStep(Integer id);
}
再配置EmployeeMapper.xml
的resultMap
标签,
dept
属性使用association
标签指定,association
的分步查询用select
属性指定要调用的接口全类名.方法名column
标签指定,使用第一步结果中的哪一列作为第二步的参数<resultMap type="com.atguigu.bean.Employee" id="MyEmpWithDeptByStep">
<id column="id" property="id"/>
<result column="last_name" property="lastName"/>
<result column="gender" property="gender"/>
<result column="email" property="email"/>
<association property="dept"
select="com.atguigu.dao.DepartmentMapper.selectDeptById"
column="dept_id">
<id column="dept_id" property="id"/>
<result column="dept_name" property="deptName"/>
association>
resultMap>
写Java测试代码:
@Test
public void test7() {
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
SqlSession openSession = sqlSessionFactory.openSession();
try {
EmployeeMapperPlus mapper = openSession.getMapper(EmployeeMapperPlus.class);
Employee employee = mapper.selectEmpWithDeptByStep(7);
System.out.println(employee);
} finally {
openSession.close();
}
}
查询结果 成功封装了dept属性:
Employee [id=7, lastName=李思, [email protected], gender=0, dept=Department [id=2, deptName=市场部]]
懒加载:即按需加载,要用的时候才会加载。
官方文档说明:
lazyLoadingEnabled
:延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置fetchType
属性来覆盖该项的开关状态。
aggressiveLazyLoading
:开启时,任一方法的调用都会加载该对象的所有延迟加载属性。 否则,每个延迟加载属性会按需加载(参考lazyLoadTriggerMethods
)。
配置MyBatis配置文件:
<settings>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false "/>
settings>
Java测试代码 先打印员工姓名,然后再打印员工部门:
@Test
public void test7() {
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
SqlSession openSession = sqlSessionFactory.openSession();
try {
EmployeeMapperPlus mapper = openSession.getMapper(EmployeeMapperPlus.class);
Employee employee = mapper.selectEmpWithDeptByStep(7);
System.out.println(employee.getLastName());
System.out.println(employee.getDept());
} finally {
openSession.close();
}
}
运行结果 分为2次查询的SQL语句:
2021-07-04 14:08:54,156 [main] DEBUG [com.atguigu.dao.EmployeeMapperPlus.selectEmpWithDeptByStep] - ==> Preparing: select * from tbl_employee where id = ?
2021-07-04 14:08:54,457 [main] DEBUG [com.atguigu.dao.EmployeeMapperPlus.selectEmpWithDeptByStep] - <== Total: 1
李思
2021-07-04 14:08:54,459 [main] DEBUG [com.atguigu.dao.DepartmentMapper.selectDeptById] - ==> Preparing: select * from tbl_dept where id = ?
2021-07-04 14:08:54,462 [main] DEBUG [com.atguigu.dao.DepartmentMapper.selectDeptById] - <= Total: 1
Department [id=2, deptName=市场部]
当只查询姓名时,则不会执行第二步,也就是不会发送查询部门的SQL语句。
当要查询部门相关的信息时,才会发送查询部门的SQL语句。
要查询信息和部门下的所有员工信息,先在部门类中增加员工列表属性。
public class Department {
private Integer id;
private String deptName;
// 部门下的所有员工列表
private List<Employee> emps;
}
在DepartmentMapper
接口中增加查询部门信息携带员工列表的方法:
public interface DepartmentMapper {
public Department selectDeptById(Integer id);
public Department selectDeptWithEmps(Integer id);
}
配置DepartmentMapper.xml
中的resultMap:
collection
标签指定将对象封装到集合ofType
属性指定将数据封装为什么类型property
指定要封装到类的哪个属性中 <resultMap type="com.atguigu.bean.Department" id="deptWithEmps">
<id column="id" property="id"/>
<result column="dept_name" property="deptName"/>
<collection property="emps" ofType="com.atguigu.bean.Employee">
<id column="emp_id" property="id"/>
<result column="last_name" property="lastName"/>
<result column="gender" property="gender"/>
<result column="email" property="email"/>
collection>
resultMap>
配置select
标签,部门表左连接员工信息表,一对多:
<select id="selectDeptWithEmps" resultMap="deptWithEmps">
select a.*,b.id as emp_id,b.last_name,b.gender,b.email
from tbl_dept a
left join tbl_employee b
on a.id = b.dept_id
where a.id = #{id}
</select>
编写Java测试代码:
@Test
public void test8() {
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
SqlSession openSession = sqlSessionFactory.openSession();
try {
DepartmentMapper mapper = openSession.getMapper(DepartmentMapper.class);
Department deptWithEmps = mapper.selectDeptWithEmps(1);
System.out.println(deptWithEmps);
} finally {
openSession.close();
}
}
运行结果 成功封装了员工信息到部门里:
Department [id=1, deptName=开发部, emps=[Employee [id=1, lastName=tom, [email protected], gender=0], Employee [id=12, lastName=王五, [email protected], gender=0]]]
小结:
感觉collection
标签和association
标签用法区别不大:
association
标签是指定单个对象的关联查询,select(去哪查)
和colunm(用什么参数查)
属性;
collection
标签是多个对象的关联查询,并将结果封装到集合中,使用ofType
属性指定(把什么封装成集合)
。
分步查询:先查询部门信息,然后通过部门信息中的部门id
查找员工表中的数据。
select * from tbl_dept where id = #{id}
select * from tbl_employee where dept_id = #{id}
先在DepartmentMapper
接口中新增分步查询方法:
public interface DepartmentMapper {
public Department selectDeptById(Integer id);
public Department selectDeptWithEmps(Integer id);
public Department selectDeptWithEmpsByStep(Integer id);
}
在EmployeeMapper
接口中新增按部门编号查询方法:
//按部门编号查询员工信息
public List<Employee> getEmpByDeptId(String id);
写EmployeeMapper.xml
实现方法:
<select id="getEmpByDeptId" resultType="com.atguigu.bean.Employee">
select * from tbl_Employee
where dept_id = #{dept_id}
select>
写DepartmentMapper.xml
的resultMap
:
collection
标签:表示将数据最终封装为集合形式property
属性:表示将数据封装到对象的哪一个属性中select
属性:去哪查column
属性:用什么作为参数查 <resultMap type="com.atguigu.bean.Department" id="deptWithEmpsByStep">
<id column="id" property="id"/>
<result column="dept_name" property="deptName"/>
<collection property="emps"
select="com.atguigu.dao.EmployeeMapper.getEmpByDeptId"
column="id">
<id column="id" property="id"/>
<result column="last_name" property="lastName"/>
<result column="gender" property="gender"/>
<result column="email" property="gender"/>
collection>
resultMap>
写select
标签,调用上面的resultMap
完成查询
<select id="selectDeptWithEmpsByStep" resultMap="deptWithEmpsByStep">
select * from tbl_dept
where id = #{id}
select>
写Java测试代码:
@Test
public void test9() {
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
SqlSession openSession = sqlSessionFactory.openSession();
try {
DepartmentMapper mapper = openSession.getMapper(DepartmentMapper.class);
Department deptWithEmps = mapper.selectDeptWithEmpsByStep(1);
System.out.println(deptWithEmps.getDeptName());
System.out.println(deptWithEmps.getEmps());
System.out.println(deptWithEmps);
} finally {
openSession.close();
}
}
输出结果 可以看到懒加载还是生效的 分了2次SQL
语句:
2021-07-04 14:31:57,088 [main] DEBUG [com.atguigu.dao.DepartmentMapper.selectDeptWithEmpsByStep] - ==> Preparing: select * from tbl_dept where id = ?
2021-07-04 14:31:57,304 [main] DEBUG [com.atguigu.dao.DepartmentMapper.selectDeptWithEmpsByStep] - <= Total: 1
开发部
2021-07-04 14:31:57,306 [main] DEBUG [com.atguigu.dao.EmployeeMapper.getEmpByDeptId] - ==> Preparing: select * from tbl_Employee where dept_id = ?
2021-07-04 14:31:57,311 [main] DEBUG [com.atguigu.dao.EmployeeMapper.getEmpByDeptId] - <= Total: 2
[Employee [id=1, lastName=tom, [email protected], gender=0], Employee [id=12, lastName=王五, [email protected], gender=0]]
Department [id=1, deptName=开发部, emps=[Employee [id=1, lastName=tom, [email protected], gender=0], Employee [id=12, lastName=王五, [email protected], gender=0]]]
第一次打印部门名称的时候,并没有执行查询员工信息的SQL
语句,当下面打印员工信息的时候,才执行查询员工信息的SQL
。
当分步查询条件需要多个参数时,可以使用map键值对的形式,将值传递给colunm属性。
例如:
<collect colunm ="{key1=colunm1,key2=colunm2}">
fetchType属性可局部控制该查询是否使用懒加载,默认值为lazy。
fetchType=“lazy”:表示使用延迟加载;
例如:
<collect fetchType="eager">
鉴别器:MyBatis中resultMap标签可以使用discriminator鉴别器子标签,对某列的值进行判断,然后根据判断的结果,改变其封装行为。
老板提的离谱需求:
如果员工性别=0,则查询对应的部门信息。
如果员工性别=1,则不用查询部门信息,但是需要把eamil邮箱改成last_name姓名。
这需求一看就很离谱,但没办法,他给的太多了。开干。
老规矩还是先在接口中新增方法:
public interface EmployeeMapperPlus {
public Employee selectById(Integer id);
public Employee selectWithDeptById(Integer id);
public Employee selectWithDeptById2(Integer id);
public Employee selectEmpWithDeptByStep(Integer id);
//按照员工性别判断查询
public Employee selectEmpConditionByGender(Integer id);
}
写resultMap
:
<resultMap type="com.atguigu.bean.Employee" id="EmpConditionByGender">
<id column="id" property="id"/>
<result column="last_name" property="lastName"/>
<result column="gender" property="gender"/>
<result column="email" property="email"/>
<discriminator javaType="string" column="gender">
<case value="0" resultType="com.atguigu.bean.Employee">
<association property="dept"
select="com.atguigu.dao.DepartmentMapper.selectDeptById"
column="dept_id">
association>
case>
<case value="1" resultType="com.atguigu.bean.Employee">
<result column="last_name" property="email"/>
case>
discriminator>
resultMap>
写select
标签:
<select id="selectEmpConditionByGender" resultMap="EmpConditionByGender">
select * from tbl_employee
where id = #{id}
select>
写Java开查,先查一个性别=0的:
@Test
public void test10() {
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
SqlSession openSession = sqlSessionFactory.openSession();
try {
EmployeeMapperPlus mapper = openSession.getMapper(EmployeeMapperPlus.class);
Employee empConditionByGender = mapper.selectEmpConditionByGender(7);
System.out.println(empConditionByGender);
System.out.println(empConditionByGender.getDept());
} finally {
openSession.close();
}
}
输出结果:
2021-07-04 15:53:33,172 [main] DEBUG [com.atguigu.dao.EmployeeMapperPlus.selectEmpConditionByGender] - ==> Preparing: select * from tbl_employee where id = ?
2021-07-04 15:53:33,322 [main] DEBUG [com.atguigu.dao.EmployeeMapperPlus.selectEmpConditionByGender] - <= Total: 1
2021-07-04 15:53:33,323 [main] DEBUG [com.atguigu.dao.DepartmentMapper.selectDeptById] - ==> Preparing: select * from tbl_dept where id = ?
2021-07-04 15:53:33,324 [main] DEBUG [com.atguigu.dao.DepartmentMapper.selectDeptById] - <= Total: 1
Employee [id=7, lastName=李思, [email protected], gender=0]
Department [id=2, deptName=市场部]
正常查出了部门信息
再查一个性别=1的:
输出结果:
2021-07-04 15:58:44,942 [main] DEBUG [com.atguigu.dao.EmployeeMapperPlus.selectEmpConditionByGender] - => Preparing: select * from tbl_employee where id = ?
2021-07-04 15:58:44,990 [main] DEBUG [com.atguigu.dao.EmployeeMapperPlus.selectEmpConditionByGender] - => Parameters: 1(Integer)
2021-07-04 15:58:45,014 [main] DEBUG [com.atguigu.dao.EmployeeMapperPlus.selectEmpConditionByGender] - <= Total: 1
Employee [id=1, lastName=tom, email=tom, gender=1]
null
正常没有显示部门信息,
邮箱也改为了姓名,顺利完成
哎 真香
resultMap就到这里了
再写就要提桶跑路了
下一篇:动态SQL