寫在前面
今天使用mybatis實現多表查詢,記錄一下其中遇到的坑
mybatis多表查詢簡介
mybatis多表查詢主要有兩個方式,通俗易懂的來說就是一個是查詢少量屬性(association),一個是把多個結果封裝成list(collection),我現在對mybatis的理解害不是很深入,用大白話的方法給大家分享一下我的理解。
association用法
association用法很簡單,我貼一段代碼
<mapper namespace="com.example.springbootvue.mapper.UserMapper">
<resultMap id="UserMap" type="com.example.springbootvue.entity.User">
<id column="user_id" jdbcType="INTEGER" property="userId"/>
<result column="username" jdbcType="VARCHAR" property="username"/>
<result column="role_id" jdbcType="INTEGER" property="roleId"/>
<association property="roleName" column="role_id"
select="com.example.springbootvue.mapper.UserMapper.getRoleName">
</association>
<select id="getRoleName" resultType="java.lang.String" parameterType="integer">
select role_name
from sp_role
where role_id = #{value}
</select>
這個resultMap被我簡化過,方便大家觀看,這里resultMap指向的是我的User類,我在User類中定義了roleId,這是Role類中的主鍵,這個實例的目的主要是查詢用戶和用戶的角色
在association中,roleName是User類中的外鍵,colum是傳入getRoleName方法中的參數,沒有仔細查詢資料,感覺association像回調函數,先找到User,再通過User中的role_id去Role表中查詢role_name,事實上好像也真是這樣,我debug中mybatis確實像數據庫發起了兩次請求
2021-05-13 23:22:30.499 INFO 4576 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2021-05-13 23:22:31.305 INFO 4576 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
2021-05-13 23:22:31.315 DEBUG 4576 --- [ main] c.e.s.m.UserMapper.selectByPrimaryKey : ==> Preparing: select user_id , username, qq_open_id, `password`, user_email, user_email_code, is_active, user_sex, user_qq, user_tel, user_xueli, user_hobby, user_introduce, create_time, update_time,role_id from sp_user where user_id = ?
2021-05-13 23:22:31.345 DEBUG 4576 --- [ main] c.e.s.m.UserMapper.selectByPrimaryKey : ==> Parameters: 1(Integer)
2021-05-13 23:22:31.372 DEBUG 4576 --- [ main] c.e.s.mapper.UserMapper.getRoleName : ====> Preparing: select role_name from sp_role where role_id = ?
2021-05-13 23:22:31.373 DEBUG 4576 --- [ main] c.e.s.mapper.UserMapper.getRoleName : ====> Parameters: 31(Integer)
2021-05-13 23:22:31.375 DEBUG 4576 --- [ main] c.e.s.mapper.UserMapper.getRoleName : <==== Total: 1
2021-05-13 23:22:31.379 DEBUG 4576 --- [ main] c.e.s.m.UserMapper.selectByPrimaryKey : <== Total: 1
實錘!!
查詢字段有null的解決方案
如果查詢出來有字段是null,檢查一下sql標簽中的colum
<sql id="Base_Column_List">
user_id
, username, qq_open_id, `password`, user_email, user_email_code, is_active,
user_sex, user_qq, user_tel, user_xueli, user_hobby, user_introduce, create_time,
update_time,role_id
</sql>
這個xml是我用mybatis-generate生成的,檢查一下里面的字段是否都對應了數據庫中的colum,我之前roleName一直查詢不出來,就是因為我漏掉的role_id,導致我查詢出來的user中role_id是null,
在association中的select中的方法
select中的方法最好是加上路徑(com.xxx.xxx.xxx.xxxMapper.xxx),檢查方法中的形參是否正確(反正我在這里給自己挖坑了,大家這么聰明應該不會在這里掉下去)
collection
colletion是我實現多級菜單查詢用到的,還是先上代碼
<resultMap id="menuMap" type="com.example.springbootvue.entity.Menu">
<id column="ps_id" jdbcType="SMALLINT" property="psId"/>
<result column="ps_name" jdbcType="VARCHAR" property="psName"/>
<result column="ps_pid" jdbcType="SMALLINT" property="psPid"/>
<collection property="children" ofType="com.example.springbootvue.entity.Menu"
column="ps_id" select="findMenuByParentId"/>
</resultMap>
我在Menu類中定義了一個列表List<Menu> children
,所以colection property=‘children’
(colection集合嘛,肯定是list類型)
ofType
指向Menu
這個類(畢竟children是Menu的屬性嘛),同樣的 column
可以理解為是后面select=‘findMenuByParentId’
的參數
然后不管是菜單有多少級,它都可以給你全部嵌套進去(經典套娃)
缺點就是一次只能查詢一個一級菜單(我的一級菜單有五個,只能分五次查詢來解決了,大佬有好的建議還請指教)
我是末尾
希望大家的代碼永無bug!!!
奧里給。