mybatis学习笔记之——mybatis的Mapper XML文件中resultMap属性

resultMap

resultMap:自定义结果集映射规则,自定义某个JavaBean的封装规则。

id:唯一id,方便引用。

type:自定义规则的Java类。

具体其他属性详细信息和配置代码如下:

<resultMap id="MyEmp" type="com.test.mybatis.bean.Employee">
    <!--
    id:指定主键列的封装规则(主键也可以使用result来定义)
    column:指定哪一列
    property:指定对应的javaBean属性
    -->
    <id column="id" property="id"></id>

    <!--
    result:定义普通列封装规则
    -->
    <result column="last_name" property="lastName"></result>

    <!--其他不指定的列会自动封装:我们只要写resultMap,就尽量把所有的列都写上-->
    <result column="email" property="email"></result>
    <result column="gender" property="gender"></result>
</resultMap>

<select id="getEmpById" resultMap="MyEmp">
    select * from tbl_employee where id = #{id}
</select>

如果出现如下场景:查询Employee的同时查询员工对应的部门,规定一个员工有与之对应的部门信息(员工信息表中会保存部门信息的主键作为外键);数据库如下设置如下(SQL server数据库):

员工表tbl_employee:

CREATE TABLE [dbo].[tbl_employee] (
[id] int NOT NULL IDENTITY(1,1) ,
[last_name] varchar(255) COLLATE Chinese_PRC_CI_AS NULL ,
[gender] char(1) COLLATE Chinese_PRC_CI_AS NULL ,
[email] varchar(255) COLLATE Chinese_PRC_CI_AS NULL ,
[d_id] int NULL ,
CONSTRAINT [PK__tbl_empl__3213E83F8C42E8B6] PRIMARY KEY ([id]),
CONSTRAINT [FK__tbl_employ__d_id__1273C1CD] FOREIGN KEY ([d_id]) REFERENCES [dbo].[tbl_dept] ([id]) ON DELETE NO ACTION ON UPDATE CASCADE
)
ON [PRIMARY]
GO

DBCC CHECKIDENT(N'[dbo].[tbl_employee]', RESEED, 6)
GO

其中数据如下图:

部门表tbl_dept:

CREATE TABLE [dbo].[tbl_dept] (
[id] int NOT NULL IDENTITY(1,1) ,
[dept_name] varchar(255) COLLATE Chinese_PRC_CI_AS NULL ,
CONSTRAINT [PK__tbl_dept__3213E83F4110434E] PRIMARY KEY ([id])
)
ON [PRIMARY]
GO

DBCC CHECKIDENT(N'[dbo].[tbl_dept]', RESEED, 2)
GO

其中数据如下图:

下面我们有两种方法来实现:

联合查询:级联属性封装结果集

分步查询:第一步,按照员工id查询出员工id;第二步,根据员工id信息中的d_id值去部门表中查询出部门信息;第三步,将查询出的部门设置到员工中。

具体实现如下:

我们首先编写实体类Employee和Department:

public class Employee {
    private Integer id;
    private String lastName;
    private String email;
    private String gender;
    private Department 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;
    }
    public Department getDept() {
        return dept;
    }
    public void setDept(Department dept) {
        this.dept = dept;
    }
    @Override
    public String toString() {
        return "Employee{" +
                "id=" + id +
                ", lastName='" + lastName + '\'' +
                ", email='" + email + '\'' +
                ", gender='" + gender + '\'' +
                '}';
    }
    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 class Department {
    private Integer id;
    private String departmentName;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getDepartmentName() {
        return departmentName;
    }
    public void setDepartmentName(String departmentName) {
        this.departmentName = departmentName;
    }
    @Override
    public String toString() {
        return "Department{" +
                "id=" + id +
                ", departmentName='" + departmentName + '\'' +
                '}';
    }
    public Department() {
    }
    public Department(Integer id, String departmentName) {
        this.id = id;
        this.departmentName = departmentName;
    }
}

然后我们编写相关接口和方法:

public interface DepartmentMapper {
    public Department getDeptById(Integer id);
}
public interface EmployeeMapperPlus {
    public Employee getEmpAndDept(Integer id);
    public Employee getEmpByIdStep(Integer id);
}

然后我们编写相关配置文件:

全局配置文件mybatis-config.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.microsoft.sqlserver.jdbc.SQLServerDriver"/>
                <property name="url" value="jdbc:sqlserver://127.0.0.1:1433;DatabaseName=mybatis"/>
                <property name="username" value="sa"/>
                <property name="password" value="sa123456"/>
            </dataSource>
        </environment>
    </environments>

    <!-- 将我们写好的sql映射文件注册到全局配置文件中 -->
    <mappers>
        <mapper resource="EmployeeMapperPlus.xml"/>
        <mapper resource="DepartmentMapper.xml"/>
    </mappers>

</configuration>

然后编写DepartmentMapper.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.test.mybatis.dao.DepartmentMapper">

    <select id="getDeptById" resultType="com.test.mybatis.bean.Department">
        select id,dept_name departmentName from tbl_dept where id =#{id};
    </select>
</mapper>

然后编写EmployeeMapperPlus.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.test.mybatis.dao.EmployeeMapperPlus">

    <!--
    联合查询:级联属性封装结果集
    -->
    <resultMap id="MyEmpAndDept" type="com.test.mybatis.bean.Employee">
        <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>

    <!--
    使用association定义关联的单个对象的封装规则;
    -->
    <resultMap id="MyEmpAndDept2" type="com.test.mybatis.bean.Employee">
        <id column="id" property="id"/>
        <result column="last_name" property="lastName"/>
        <result column="gender" property="gender"/>
        <!--
        可以指定联合的JavaBean对象
        property="dept":指定哪个属性是联合的对象
        javaType:指定这个属性对象的类型,不能省略
        -->
        <association property="dept" javaType="com.test.mybatis.bean.Department">
            <id column="did" property="id"/>
            <result column="dept_name" property="departmentName"/>
        </association>
    </resultMap>

    <select id="getEmpAndDept" resultMap="MyEmpAndDept2">
        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>

    <!--
    使用association进行分步查询
    -->
    <resultMap id="MyEmpByStep" type="com.test.mybatis.bean.Employee">
        <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.test.mybatis.dao.DepartmentMapper.getDeptById"
            column="d_id">
        </association>
    </resultMap>

    <select id="getEmpByIdStep" resultMap="MyEmpByStep">
        select * from tbl_employee where id = #{id}
    </select>

</mapper>

然后我们进行测试MyBatisTest2:

public class MyBatisTest2 {

    public SqlSessionFactory getSqlSessionFactory() throws IOException {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        return new SqlSessionFactoryBuilder().build(inputStream);
    }

    @Test
    public void test05() 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);
            Employee empAndDept = mapper.getEmpByIdStep(5);
            System.out.println(empAndDept);
            System.out.println(empAndDept.getDept());
        }finally {
            openSession.close();
        }
    }
}

其中注释掉的是级联查询的测试。项目结构如下:

分布查询测试结果如下:

我们查询出了我们想要的结果。

分步查询的好处:

可以延迟加载,也叫懒加载。我们每次查询Employee对象的时候,都将一起查询出来部门信息,我们可以在需要的时候再去查询。我们需要在mybatis-config.xml加入两个配置:

<settings>
    <setting name="lazyLoadingEnabled" value="true"/>
    <setting name="aggressiveLazyLoading" value="false"/>
</settings>

lazyLoadingEnabled:延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 默认值为false。

aggressiveLazyLoading:当开启时,任何方法的调用都会加载该对象的所有属性。否则,每个属性会按需加载。默认值为false。

这两个属性配置好之后,我们修改测试类,只输出System.out.println(empAndDept.getEmail());,再次测试:

 跟上面的测试结果图对比,这次我们只查询了员工信息,并没有查询部门信息。

除了association,我们还需要了解一下collection。嵌套结果集的方式,使用collection标签定义关联的集合类型的属性封装规则。

ofType:指定集合里面元素的类型。

fetchType="lazy":表示使用延迟加载,lazy:延迟;eager:立即加载。

还有一个discriminator鉴别器:mybatis可以使用discriminator判断某列的值,根据某列的值改变封装行为。

javaType:列值对应的Java类型

column:指定判定的类名

 如果查询部门的时候将部门对应的所有员工信息也查询出来,我们就可以用collection标签来实现:

<resultMap id="MyDept" type="com.test.mybatis.bean.Department">
        <id column="did" property="id"></id>
        <result column="dept_name" property="departmentName"></result>

        <collection property="emps" ofType="com.test.mybatis.bean.Employee" fetchType="lazy">
            <!--定义这个集合中元素的封装规则-->
            <id column="eid" property="id"></id>
            <result column="last_name" property="lastName"></result>
            <result column="email" property="email"></result>
            <result column="gender" property="gender"></result>
            <!--鉴别器-->
            <discriminator javaType="string" column="gender">
                <!--此处的resultType不能少,也可以是resultMap-->
                <case value="0" resultType="com.test.mybatis.bean.Employee">
                    <!--编写相关信息-->
                </case>
                <case value="1" resultType="com.test.mybatis.bean.Employee">
                    <!--编写相关信息-->
                </case>
            </discriminator>
        </collection>
    </resultMap>

    <select id="getDeptByIdPlus" resultMap="MyDept">
        SELECT d.id did, d.dept_name dept_name,e.id eid,e.last_name last_name,e.email email,e.gender gender 
        from tbl_dept d LEFT JOIN tbl_employee e on d.id = e.d_id WHERE d.id=#{id};
</select>

 

还需要补充的一点是,在做分步查询的时候,column表示将某一列的值传给这个方法,如何我们要将多列的值传递给某方法,我们将多列的值封装map传递:

column="{key1=column1,key2=column2}

 

注:此文章为【尚硅谷_MyBatis_入门到进阶】学习笔记。原视频中是Java代码,连接的数据库是Mysql,开发工具为eclipse。因个人学习需求,此文章为Java代码,但是数据库是SQL server,开发工具用的是IDEA。

 

 

  • 4
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值