在涉及到關系型數據庫增刪查改的業務時,我比較喜歡用 MyBatis-Plus ,開發效率極高。具體的使用可以參考官網,或者自己上手摸索感受壹下。
下面簡單總結壹下在 MyBatis-Plus 中如何使用 ResultMap 。
先看個例子:
有如下兩張表:
其中, tb_hero 中的 bid 關聯 tb_book 表的 id 。
下面先看 Hero 實體類的代碼,如下:
註意了,我特地把 tb_hero 表中的 bid 字段映射成實體類 Hero 中的 bookId 屬性。
MyBatis-Plus 打印出的 SQL 為:
沒毛病, MyBatis-Plus 會根據 @TableField 指定的映射關系,生成對應的 SQL 。
MyBatis-Plus 打印出的 SQL 為:
也沒毛病,可以看到生成的 SELECT 中把 bid 做了別名 bookId 。
比如現在我想連接 tb_hero 與 tb_book 這兩張表,如下:
查詢 MyBatis-Plus 打印出的 SQL 為:
SQL沒啥問題,過濾與分頁也都正常,但是此時妳會發現 bookId 屬性為 null ,如下:
為什麽呢?
調用 BaseMapper 中內置的 selectById() 方法並沒有出現這種情況啊?
回過頭來再對比壹下在 HeroMapper 中自己定義的查詢與 MyBatis-Plus 自帶的 selectById() 有啥不同,還記得上面的剛剛的測試嗎,生成的SQL有啥不同?
原來, MyBatis-Plus 為 BaseMapper 中內置的方法生成SQL時,會把 SELECT 子句中 bid 做別名 bookId ,而自己寫的查詢 MyBatis-Plus 並不會幫妳修改 SELECT 子句,也就導致 bookId 屬性為 null 。
在這裏就是 tb_hero 表中的 bid 字段映射成實體類 Hero 中的 bid 屬性。這樣當然可以解決問題,但不是本篇講的重點。
在 @TableName 設置 autoResultMap = true
然後在自定義查詢中添加 @ResultMap 註解,如下:
這樣,也能解決問題。
下面簡單看下源碼, @ResultMap("mybatis-plus_實體類名") 怎麽來的。
詳情見: com.baomidou.mybatisplus.core.metadata.TableInfo#initResultMapIfNeed()
註意看上面的字符串 id 的構成,妳應該可以明白。
思考: 這種方式的 ResultMap 默認是強綁在壹個 @TableName 上的,如果是某個聚合查詢或者查詢的結果並非對應壹個真實的表怎麽辦呢?有沒有更優雅的方式?
基於上面的思考,我做了下面簡單的實現:
關鍵代碼其實沒有幾行,耐心看下應該不難懂。
還是用例子來說明更直觀。
下面是壹個聚合查詢:
其中 BookAgg 的定義如下,在實體類上使用了 @AutoResultMap 註解: