mybatis總結(三)(resultMap和高級映射-級聯)


在真實的業務場景中,使用resultType進行輸出映射,只有查詢出來的列名和pojo(實體bean)中的屬性名一致,該列才可以映射成功。簡單來說也就是你的數據庫字段和JavaBean里的字段名稱必須一致才能映射成功。

當JavaBean中的字段名和數據庫字段名稱有不同的時候,或者是多表查詢的時候,一般會使用resultMap。

 

什么是resultMap

 

resultMap是Mybatis最強大的元素,它可以將查詢到的復雜數據(比如查詢到幾個表中數據)映射到一個結果集當中。

 

resultMap的作用

 

resultMap的作用是定義映射規則、級聯的更新、定制類型轉化器等。resultMap定義的主要是一個結果集的映射關系,也就是sql到java bean的映射關系定義,它也支持級聯等特性。

 

resultMap的元素構成

 

resultMap元素的子元素:

<resultMap>
    <constructor>
        <idArg/>
        <arg>
    </constructor>
    <id/>
    <result/>
    <association/>
    <collection/>
    <discriminator>
        <case/>
    </discriminator>
</resultMap>

 

 resultMap的語法

 

<!--column不做限制,可以為任意表的字段,而property須為type 定義的pojo屬性-->
<resultMap id="唯一的標識" type="映射的pojo對象">
  <id column="表的主鍵字段,或者可以為查詢語句中的別名字段" jdbcType="字段類型" property="映射pojo對象的主鍵屬性" />
  <result column="表的一個字段(可以為任意表的一個字段)" jdbcType="字段類型" property="映射到pojo對象的一個屬性(須為type定義的pojo對象中的一個屬性)"/>
  <association property="pojo的一個對象屬性" javaType="pojo關聯的pojo對象">
    <id column="關聯pojo對象對應表的主鍵字段" jdbcType="字段類型" property="關聯pojo對象的主席屬性"/>
    <result  column="任意表的字段" jdbcType="字段類型" property="關聯pojo對象的屬性"/>
  </association>
  <!-- 集合中的property須為oftype定義的pojo對象的屬性-->
  <collection property="pojo的集合屬性" ofType="集合中的pojo對象">
    <id column="集合中pojo對象對應的表的主鍵字段" jdbcType="字段類型" property="集合中pojo對象的主鍵屬性" />
    <result column="可以為任意表的字段" jdbcType="字段類型" property="集合中的pojo對象的屬性" />  
  </collection>
</resultMap>

如果collection標簽是使用嵌套查詢,格式如下:

 <collection column="傳遞給嵌套查詢語句的字段參數" property="pojo對象中集合屬性" ofType="集合屬性中的pojo對象" select="嵌套的查詢語句" > 
 </collection>

注意:<collection>標簽中的column:要傳遞給select查詢語句的參數,如果傳遞多個參數,格式為column= ” {參數名1=表字段1,參數名2=表字段2} ;

 

resultMap的應用

 

 

比如,數據庫中字段名稱為id,name,age,sex 而對應java代碼中pojo的屬性名分別為id,username,age,sex。可以看出姓名列不一致,這個時候就需要使用resultMap來將字段名和屬性名對應起來,進行手動配置封裝,將結果映射到pojo中。

<!-- resultMap最終還是要將結果映射到pojo上,type就是指定映射到哪一個pojo -->
<!-- id:設置ResultMap的id -->
<resultMap type="user" id="userMap">
    <!-- 定義主鍵 ,非常重要。如果是多個字段,則定義多個id -->
    <!-- property:pojo里的屬性名 column:數據庫中的列名 -->
    <id property="id" column="id" />

    <!-- 定義普通屬性 property:pojo里的屬性名 column:數據庫中的列名-->
    <result property="username" column="name" />
    <result property="age" column="age" />
    <result property="sex" column="sex" />
</resultMap>

<!-- resultMap:填入配置的resultMap標簽的id值 -->
<select id="findUser" resultMap="userMap">
    select id,name,age,sex from user 
</select>

 

 

 級聯

 

Mybatis的級聯操作主要是針對一對多、多對一和多對多的情況而設定的。級聯是在resultMap標簽中配置的。級聯並不是必須的,好處就是獲取關聯數據便捷,但如果級聯過多會增加系統的復雜度,同時降低系統的性能。所以記錄超過3層時,就不要考慮使用級聯了,因為這樣會造成多個對象的關聯,導致系統的耦合、負載和難以維護。

 

一對一

業務場景:訂單用戶,一條訂單信息只能對應一個用戶,此為一對一。做法如下:

1. 改造訂單的pojo類:

(添加User屬性--User屬性是一個引用類型,用於存儲關聯查詢的用戶信息,因為關聯關系是一對一,所以只需要添加單個屬性即可)

//訂單類
pulic class Order{
    //原order屬性
    private int id;
    private Integer userId;
    private String number;
    private Date createtime;
    private String note;
    //新加user屬性
    private User user;
    //下面省略get和set方法
}

//用戶信息類
pulic void User{
    private int id;
    private String username;
    private String address;
    //下面省略get和set方法
}

2. 修改mapper.xml配置文件

(使用resultMap和association標簽來實現一對一)

<resultMap type="order" id="orderUserResultMap">
    <!-- 第一步:配置Order類的對應關系 -->
    <!-- property:pojo里的屬性名 column:數據庫中的列名 -->
    <id property="id" column="id" />
    <result property="userId" column="user_id" />
    <result property="number" column="number" />
    <result property="createtime" column="createtime" />
    <result property="note" column="note" />

    <!-- 第二步:配置User類的對應關系 -->
    <!-- association :配置一對一屬性 property:order里面的User屬性名 javaType:屬性類型-->
    <association property="user" javaType="user">
        <!-- id:聲明主鍵,表示user_id是關聯查詢對象的唯一標識 -->
        <!-- 簡單說就是:id標簽:(property:user表的主鍵名稱 column:對應Order表的外鍵名稱) result標簽下的都是user表的內容-->
        <id property="id" column="user_id" />
        <result property="username" column="username" />
        <result property="address" column="address" />
    </association>

</resultMap>

<!-- 一對一關聯,查詢訂單,訂單內部包含用戶屬性 -->
<select id="queryOrderUserResultMap" resultMap="orderUserResultMap">
    SELECT a.id,a.user_id,a.number,a.createtime,a.note,b.username,b.address from order a left join user b on a.user_id = b.id
</select>

3. 測試代碼:

@Test
public void testQueryOrderUserResultMap() {
    // mybatis和spring整合,整合之后,交給spring管理
    SqlSession sqlSession = this.sqlSessionFactory.openSession();
    // 創建Mapper接口的動態代理對象,整合之后,交給spring管理
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

    // 使用userMapper執行根據條件查詢用戶,結果封裝到Order類中
    List<Order> list = userMapper.queryOrderUserResultMap();
    for (Order o : list) {
        System.out.println(o);
    }
    // mybatis和spring整合,整合之后,交給spring管理
    sqlSession.close();
}

 

一對多

業務場景:訂單用戶,一個用戶對應多條訂單信息,此為一對多。做法如下:

1. 改造用戶的pojo類:

(添加訂單集合屬性)

//訂單類
pulic class Order{
    private int id;
    private Integer userId;
    private String number;
    private Date createtime;
    private String note;
    //下面省略get和set方法
}

//用戶信息類
pulic void User{
    //原用戶屬性
    private int id;
    private String username;
    private String address;
    //新加訂單集合屬性
    private List<Order> orders;
    //下面省略get和set方法
}

2. 修改mapper.xml配置文件

(使用resultMap和collection標簽來實現一對多)

<!-- 因為主要查詢的是user 所以先配置User類的結果 -->
<resultMap type="user" id="userOrderResultMap">
    <!-- 第一步:配置User類的對應關系 -->
    <id property="id" column="id" />
    <result property="username" column="username" />
    <result property="sex" column="sex" />
    <result property="address" column="address" />

    <!-- 第二步:配置order類的對應關系 -->
    <!-- property:填寫pojo類中集合類類屬性的名稱 javaType:填寫集合類型的名稱 ofType:list中內容的類型 -->
    <collection property="orders" javaType="list" ofType="order">
        <!-- 配置主鍵,是關聯Order的唯一標識 這里要注意oid 是因為下面select標簽的sql中給order的id起了別名 叫做oid-->
        <id property="id" column="oid" />
        <result property="number" column="number" />
        <result property="createtime" column="createtime" />
        <result property="note" column="note" />
    </collection>
</resultMap>

<!-- 一對多關聯,查詢訂單同時查詢該用戶下的訂單 -->
<select id="queryUserOrder" resultMap="userOrderResultMap">
    SELECT a.id,a.username,a.address,a.sex,b.id oid,b.number,b.createtime,b.note from user a left join order b on a.id = b.user_id
</select>

當然也有更多一級的一對多:collection中有collection和association,這里不多介紹。

 

多對多

業務場景:每個老師有多個學生,每個學生又有多個老師,此為多對多。用法如下:

1. 首先涉及到三張表:學生表(student)、教師表(teacher)、學生和教師關系表(tu_teach_rel)

public class Student{
    //學生表原屬性
    private String id;
    private String name;
    private int age;
    private Gender gender;
    //學生表新加屬性
    private List<Teacher> teachers;
    //下面省略get和set方法
}

public class Teacher{
    //教師表原屬性
    private int id;
    private String name;
    private Gender gender;
    private Subject subject;
    private String degree;
    //教師表新加屬性
    private List<Student> students;
    //下面省略get和set方法
}

public class stu_teach_rel{
    //學生教師關系表
    private int id;
    private int stu_id;
    private int teach_id;
    //這里不需要加東西
    //下面省略get和set方法
}

2. mapper.xml配置文件

<mapper namespace="com.yihaomen.mybatis.dao.StudentMapper">
    <resultMap id="studentMap" type="Student">
        <id property="id" column="id" />
        <result property="name" column="name" />
        <result property="age" column="age" />
        <result property="gender" column="gender" typeHandler="org.apache.ibatis.type.EnumOrdinalTypeHandler" />
    </resultMap>
    <resultMap id="collectionMap" type="Student" extends="studentMap">
        <collection property="teachers" ofType="Teacher">
            <id property="id" column="teach_id" />
            <result property="name" column="tname"/>
            <result property="gender" column="tgender" typeHandler="org.apache.ibatis.type.EnumOrdinalTypeHandler"/>
            <result property="subject" column="tsubject" typeHandler="org.apache.ibatis.type.EnumTypeHandler"/>
            <result property="degree" column="tdegree" javaType="string" jdbcType="VARCHAR"/>
        </collection>
    </resultMap>
    <select id="selectStudents" resultMap="collectionMap">
    SELECT
    s.id, s.name, s.gender, t.id teach_id, t.name tname, t.gender tgender, t.subject tsubject, t.degree tdegree
    FROM
    student s
    LEFT JOIN
    stu_teach_rel str
    ON
    s.id = str.stu_id
    LEFT JOIN
    teacher t
    ON
    t.id = str.teach_id
    </select>
</mapper>

 

總結:

一對一可以通過<association>實現,一對多和多對多通過<collection>實現。

 

參考:

1. https://www.cnblogs.com/kenhome/p/7764398.html

2. https://blog.csdn.net/qq_42780864/article/details/81429114

3. https://blog.csdn.net/lks1139230294/article/details/88087470

4. https://www.jb51.net/article/126584.htm

持續更新!!!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM