Mybatis中多表關聯時,怎麼利用association優雅寫resultMap來映射vo

  • 2019 年 11 月 14 日
  • 筆記

前言

有好一陣沒碰mybatis了,這次的項目基於性能考慮,選了mybatis,寫著寫著,發現有下面的需求,比如兩表聯查,取其中各一部分欄位,怎麼更方便地用vo來接,這裡犯了難;

我想的是,因為這個sql聯查的vo,能不能直接使用兩個表的po來接呢,比如下面這種:

Users、SeatInformation都是對應了資料庫兩張表的po  @Data  public class UserSeatUnionQueryVO {      private Users users;        private SeatInformation seatInformation;  }

折騰了2個小時,網上各種找不到類似需求,終於搞出來了,還是值得記錄和分享。

一、兩表關聯,映射到如下類型vo(拷貝單表po屬性,組合另一單表的po),怎麼寫

sql:

      <select id="selectOnlineUserBySeatState" resultMap="UserSeatUnionQueryVOResultMap">          SELECT              u.`user_id`,u.`account_status`,s.*          FROM              users u,              seat_information s          WHERE u.`user_id` = s.`user_id`                AND u.`account_status` = 1                AND u.`delete_status` = 1                AND u.`center_id` = 0                AND s.`token` IS NOT NULL                AND s.`seat_state` = 1                AND s.delete_status = 1      </select>

假設我想映射的vo如下:

@Data  public class UserSeatUnionQueryVO {        /**       * 用戶Id       */      @ApiModelProperty(value = "用戶Id")      @TableId(value = "user_id", type = IdType.ID_WORKER)      private Long userId;          /**       * 帳號狀態,-1停用,1啟用       */      @ApiModelProperty(value = "帳號狀態,-1停用,1啟用")      private Integer accountStatus;        /**       * 這裡的SeatInformation是表seat_information對應的po       */      private SeatInformation seatInformation;  }

則mapper中應該這樣寫:

UsersMapper.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.ceiec.cad.mapper.UsersMapper">        <!-- 通用查詢映射結果 -->      <resultMap id="BaseResultMap" type="com.ceiec.cad.model.Users">          <id column="user_id" property="userId" />          <result column="account_status" property="accountStatus" />      </resultMap>          <resultMap id="UserSeatUnionQueryVOResultMap" type="com.ceiec.cad.service.UserSeatUnionQueryVO">          <id column="user_id" property="userId" />          <result column="account_status" property="accountStatus" />          <association property="seatInformation"  javaType="com.ceiec.cad.model.SeatInformation" resultMap="com.ceiec.cad.mapper.SeatInformationMapper.BaseResultMap">            </association>        </resultMap>          <select id="selectOnlineUserBySeatState" resultMap="UserSeatUnionQueryVOResultMap">          SELECT              u.`user_id`,u.`account_status`,s.*          FROM              users u,              seat_information s          WHERE u.`user_id` = s.`user_id`                AND u.`account_status` = 1                AND u.`delete_status` = 1                AND u.`center_id` = 0                AND s.`token` IS NOT NULL                AND s.`seat_state` = 1                AND s.delete_status = 1      </select>  </mapper>  
SeatInformationMapper.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.ceiec.cad.mapper.SeatInformationMapper">        <!-- 通用查詢映射結果 -->      <resultMap id="BaseResultMap" type="com.ceiec.cad.model.SeatInformation">          <id column="seat_information_id" property="seatInformationId" />          //省略無關程式碼      </resultMap>    </mapper>  

二、兩表關聯,映射到如下類型vo(組合兩表po),怎麼寫

上面的方案呢,假設A關聯B,在vo里,相當於是把B組合進了A;我想的是,能不能新建一個vo,同時組合A和B呢,比如下面這樣:

@Data  public class UserSeatUnionQueryVO {      private Users users;        private SeatInformation seatInformation;  }  

sql:

和方案一一樣。

UsersMapper.xml:

      <resultMap id="UserSeatUnionQueryVOResultMap" type="com.ceiec.cad.service.UserSeatUnionQueryVO">          <association property="users"  javaType="com.ceiec.cad.model.Users" resultMap="com.ceiec.cad.mapper.UsersMapper.BaseResultMap">            </association>          <association property="seatInformation"  javaType="com.ceiec.cad.model.SeatInformation" resultMap="com.ceiec.cad.mapper.SeatInformationMapper.BaseResultMap">            </association>        </resultMap>  

注意這裡的 association元素中的resultMap欄位,引用了其他Mapper文件的BaseResultMap

格式是:其他Mapper文件的namespace,加上resultMap的名字。

這裡附上SeatInformationMapper.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.ceiec.cad.mapper.SeatInformationMapper">        <!-- 通用查詢映射結果 -->      <resultMap id="BaseResultMap" type="com.ceiec.cad.model.SeatInformation">          <id column="seat_information_id" property="seatInformationId" />          //省略無關      </resultMap>    </mapper>  

下面附上完整的usersMapper.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.ceiec.cad.mapper.UsersMapper">        <!-- 通用查詢映射結果 -->      <resultMap id="BaseResultMap" type="com.ceiec.cad.model.Users">          <id column="user_id" property="userId" />          <result column="account_status" property="accountStatus" />      </resultMap>          <resultMap id="UserSeatUnionQueryVOResultMap" type="com.ceiec.cad.service.UserSeatUnionQueryVO">          <association property="users"  javaType="com.ceiec.cad.model.Users" resultMap="com.ceiec.cad.mapper.UsersMapper.BaseResultMap">            </association>          <association property="seatInformation"  javaType="com.ceiec.cad.model.SeatInformation" resultMap="com.ceiec.cad.mapper.SeatInformationMapper.BaseResultMap">            </association>        </resultMap>          <select id="selectOnlineUserBySeatState" resultMap="UserSeatUnionQueryVOResultMap">          SELECT              u.*,s.*          FROM              users u,              seat_information s          WHERE u.`user_id` = s.`user_id`                AND u.`account_status` = 1                AND u.`delete_status` = 1                AND u.`center_id` = 0                AND s.`token` IS NOT NULL                AND s.`seat_state` = 1                AND s.delete_status = 1      </select>  </mapper>  

展示下效果:

可以看到,最後這種,這麼寫沒問題。

三、官網文檔

我在官網看了半天,後來才找到類似的例子:

https://mybatis.org/mybatis-3/sqlmap-xml.html

因為文檔很長,上面這個圖,大家可以通過打開上面的網址後,搜索 Multiple ResultSets for Association到達該位置。