Mybatis----resultMap详解及应用(一)

接前面的博客,今天分享一下学习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标签定义主键会有底层有优化
    1. column:指定唯一列
    2. property:指定对应的javaBean属性
  • result:定义普通列封装规则
    1. column:指定唯一列
    2. 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
    • email
    • 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的请求。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值