一對一
在SysUser 類中增加SysRole字段。
1、sql語句將role.role_name映射到role.roleName上。
2、還可以在XML 映射文件中配置結果映射。
<resultMap id="userRoleMap" type ="SysUser"〉
<id property="id" column="id"/>
<result property="userName" column="use_name"/>
<result property="userPassword" column="user_password" />
<result property="role.id" column ="role_id"/>
<result property="role.roleName" column="role_name"/>
<result property="role.createTime" column="role_create_time" jdbcType="TIMESTAMP"/>
</resultMap>
為了避免不同表中存在相同的列,如create_time, 在它前面增加了"role_"前綴。
3、MyBatis是支持resultMap繼承,因此可以簡化上面的resultMap配置
<resultMap id= "userRoleMap" extends= "userMap" type= "SysUser">
<result property= "role.id" column="role_id "/>
<result property= "role.roleName" column= "role_name"/>
<result property= "role.createTime" column ="role_create_time" jdbcType= "TIMESTAMP"/>
</resultMap>
4、使用resultMap的association標簽配置
<resultMap id= "userRoleMap" extends= "userMap" type= "SysUser">
<association property="role" columnPrefix="role_" javaType="SysRole">
<result property= "id" column="role_id "/>
<result property= "roleName" column= "role_name"/>
<result property= "createTime" column ="create_time" jdbcType= "TIMESTAMP"/>
</association>
</resultMap>
association標簽的屬性property對應實體類中的屬性名,必填項。另外我們還配置了columnPrefix="role_",在寫SQL的時候,和sys_role表相關的查詢列的別名都要有"role_"前綴,在內部result配置column時,需要去掉前綴。sql:r.id role_id, r.role_name role_role_name, r.create_time role_create_time。
5、使用association 配置時還可以使用resultMap 屬性配置成一個已經存在的resultMap
<resultMap id= "roleMap" type = "SysRole">
<id property="id" column="id"/>
<result property="roleName" column= "role_name"/>
<result property="createTime" column="create_time" jdbcType = "TIMESTAMP"/>
</resultMap>
<resultMap id="userRoleMap" extends= "userMap" type="SysUser">
<association property="role" columnPrefix="role_" resultMap="roleMap"/>
</resultMap>
MyBatis 默認會給 roleMap 添加當前命名空間的前綴,代碼如下,test.mybatis.simple.mapper.UserMapper.roleMap。目前的 roleMap 是寫在UserMapper.xml中的,其實更合理的位置應該是在RoleMapper.xml中。將roleMap移動到RoleMapper.xml中后,這里的userRoleMap就不能簡單地指定為roleMap了,而是要修改為以下的樣子。
<resultMap id="userRoleMap" extends= "userMap" type="SysUser">
<association property="role" columnPrefix="role_" resultMap="test.mybatis.simple.mapper.RoleMapper.roleMap"/>
</resultMap>
上面的情況都是一種情況,這種方式的好處是減少數據庫查詢次數,減輕數據庫的壓力。缺點是由於要在應用服務器上將結果映射到不同的類上,因此也會增加應用服務器的壓力。當一定會使用到嵌套結果,並且整個復雜的SQL執行速度很快時,建議使用這種方法。
還可以利用簡單的SQL 通過多次查詢轉換為我們需要的結果,最后會將結果組合成一個對象。
<resultMap id = "userRoleMapSelect" extends = "userMap" type= "SysUser">
<association property="role" column="{id=role_id}" select="test.mybatis.simple.mapper.RoleMapper.selectRoleById" />
</resultMap>
<select id="selectUserAndRoleByIdSelect" resultMap="userRoleMapSelect">
select u.id, u.user_name, u.user_password, u.user_email, u.user_info,u.head_img, u.create_time,
ur.role_id
from sys_user u
join sys_user_role ur on u.id = ur.user_id
where u.id= #{id}
</select>
association 屬性 select :另一個查詢的id, MyBatis 會額外執行這個查詢。
column :列名(或別名),將主查詢中列的結果作為嵌套查詢的參數,配置方式如 column = {propl=coll , prop2=col2}。
fetchType :數據加載方式,可選值為lazy 和eager,分別為延遲加載和積極加載,這個配置會覆蓋全局的lazyLoadingEnabled 配置。
問題:如果主查詢結果不是1條數據,而是N條數據,那就會出現N+1問題。主SQL 會查詢一次,查詢出N 條結果,這N條結果要各自執行一次查詢,那就需要進行N次查詢。
解決辦法:fetchType="lazy"
<resultMap id = "userRoleMapSelect" extends = "userMap" type= "SysUser">
<association property="role" column="{id=role_id}"
select="test.mybatis.simple.mapper.RoleMapper.selectRoleById" fetchType="lazy"/>
</resultMap>
<select id="selectUserAndRoleByIdSelect" resultMap="userRoleMapSelect">
select u.id, u.user_name, u.user_password, u.user_email, u.user_info,u.head_img, u.create_time,
ur.role_id
from sys_user u
join sys_user_role ur on u.id = ur.user_id
where u.id= #{id}
</select >