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
到達該位置。