前言
有好一陣沒碰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
到達該位置。