接前面的博客,今天分享一下学习resultMap的笔记(几天不看,差点忘完了,回来再看看,沉淀一下!!!
且看下面这个小案例:数据库中的列名为last_name,而JavaBean中的属性名为lastName,如果不在全局配置文件settings中开启驼峰命名法映射规则,last Name属性就封装不上了,如下所示,打印出来的lastName显示为null。
Employee{id=1, lastName='null', email='112233@qq.com', gender='1', dept=null}
这时resultMap就能显现它的威力了——自定义结果集映射规则。既然是自定义,它的能力觉不仅限于此。
一、resultMap:自定义某个javaBean的封装规则
属性:
- type:自定义规则的Java类型
- id:唯一id方便引用
标签:
- id:指定主键列的封装规则,id标签定义主键会有底层有优化
- column:指定唯一列
- property:指定对应的javaBean属性
- result:定义普通列封装规则
- column:指定唯一列
- property:指定对应的javaBean属性
- 不指定的列会自动封装,但是推荐写上,出了问题方便查看
<resultMap id="mySimpleMap" type="bean.Employee">
<id column="id" property="id"/>
<result column="last_name" property="lastName"/>
<result column="email" property="email"/>
<result column="gender" property="gender"/>
</resultMap>
<!-- public Employee getEmpById(Integer id);-->
<select id="getEmpById" resultMap="mySimpleMap" >
select * from tbl_employee where id=#{id};
</select>
手动将last_name映射为lastName,这样就能解决未开启驼峰命名映射规则导致属性封装不上的问题了。
二、级联属性封装结果
对tbl_employee进行改造并新建一个tbl_dept:删掉重来也行
CREATE TABLE `tbl_employee` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`last_name` varchar(255) DEFAULT NULL,
`gender` char(1) DEFAULT NULL,
`email` varchar(255) DEFAULT NULL,
`d_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `fk_emp_dept` (`d_id`),
CONSTRAINT `fk_emp_dept` FOREIGN KEY (`d_id`) REFERENCES `tbl_dept` (`id`)
)
CREATE TABLE `tbl_dept` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`dept_name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
)
对之前的Employee.java进行改造,新增一个部门属性Department。
package bean;
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 Employee() {
}
public Employee(Integer id, String lastName, String email, String gender) {
this.id = id;
this.lastName = lastName;
this.email = email;
this.gender = gender;
}
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 + '\'' +
", dept=" + dept +
'}';
}
}
Department.java如下:
package bean;
import java.util.List;
public class Department {
private Integer id;
private String departmentName;
private List<Employee> emps;
public List<Employee> getEmps() {
return emps;
}
public void setEmps(List<Employee> emps) {
this.emps = emps;
}
public String getDepartmentName() {
return departmentName;
}
public void setDepartmentName(String departmentName) {
this.departmentName = departmentName;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
@Override
public String toString() {
return "Department{" +
"id=" + id +
", departmentName='" + departmentName + '\'' +
'}';
}
}
场景一:查出Employee的同时查询员工对应的部门
- Employee==>Department:一个员工有与之对应的部门信息:
- id
- last_name
- gender
- d_id
- dept_name
mapper接口中的方法:
public Employee getEmpAndDept(Integer id);
mapper.xml中的映射规则:
<!-- public Employee getEmpAndDept(Integer id);-->
<select id="getEmpAndDept" resultMap="myEmp2">
select e.id id,e.last_name last_name,e.gender gender,e.email email,e.d_id d_id,d.dept_name
from tbl_employee e,tbl_dept d
where e.d_id=d.id and e.id=#{id};
</select>
resultMap两种方式解决问题:
方法一:级联属性,将查出来的值手动指定封装的属性
<resultMap type="bean.Employee" id="myEmp">
<id column="id" property="id"/>
<result column="last_name" property="lastName"/>
<result column="gender" property="gender"/>
<result column="email" property="email"/>
<result column="d_id" property="dept.id"/>
<result column="dept_name" property="dept.departmentName"/>
</resultMap>
方法二:使用association定义单个对象的封装规则
association可以指定联合的JavaBean对象。
property:指定哪个属性是联合的对象
javaType:指定对象的类型
<resultMap id="myEmp2" type="bean.Employee">
<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="bean.Department">
<id column="d_id" property="id"/>
<result column="dept_name" property="departmentName"/>
</association>
</resultMap>
测试:
@Test
public void test1() throws IOException {
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
SqlSession openSession = sqlSessionFactory.openSession();
try {
EmployeeMapperPlus mapper = openSession.getMapper(EmployeeMapperPlus.class);
Employee empById = mapper.getEmpById(1);
System.out.println(empById);
}finally {
openSession.close();
}
}
输出结果:
Employee{id=1, lastName='jerry', email='112233@qq.com', gender='1', dept=Department{id=1, departmentName='开发部'}} Department{id=1, departmentName='开发部'}
三、使用association分步查询
步骤:
1. 先按照员工的id查询员工信息
2. 根据查询员工信息中的d_id值去查部门信息
3. 再将部门设置到员工中
首先将查询部门的方法写好:
DepartmentMapper接口中的方法:
public Department getDeptById(Integer id);
DepartmentMapper.xml中映射规则:
<!-- public Department getDeptById(Integer id);-->
<select id="getDeptById" resultType="bean.Department">
select id,dept_name departmentName from tbl_dept where id=#{id}
</select>
再来写员工信息相关:
EmployeeMapper接口中的方法:
public Employee getEmpByIdStep(Integer id);
EmployeeMapper.xml中映射规则:
定义关联对象的封装规则:
select:表明当前属性是调用select指定的方法查出的结果
column:指定将哪一列的值传给这个方法
流程:以下为例,使用select指定的方法(dao.DepartmentMapper.getDeptById),传入column指定的这列参数的值(select中查出来的d_id列的值),查出对象Department,并封装给property指定的Employee的属性dept。
<resultMap id="myEmpByStep" type="bean.Employee">
<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="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>
测试:将上面的测试关键部分替换掉
Employee empByIdStep = mapper.getEmpByIdStep(1);
System.out.println(empByIdStep);
System.out.println(empByIdStep.getDept());
测试结果:
Employee{id=1, lastName='jerry', email='112233@qq.com', gender='1', dept=Department{id=1, departmentName='开发部'}}
Department{id=1, departmentName='开发部'}
四、分步查询的延迟加载
在分步查询的基础上,在全局配置文件的settings中,开启lazyLoadingEnabled,关闭aggressiveLazyLoading
lazyLoadingEnabled:懒加载模式总开关,默认false。
aggressiveLazyLoading:侵入式懒加载开关,默认true,开启时所有的属性都会加载。
测试:
Employee empByIdStep = mapper.getEmpByIdStep(1);
System.out.println(empByIdStep.getlastName());
这里只打印了employee中的lastName属性,则不会向数据库发送查询对应dept的请求。