1. 程式人生 > >mybatis學習筆記之——mybatis的Mapper XML檔案中resultMap屬性

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。