【筆記】Mybatis高階查詢--使用resultMap配置一對一對映
阿新 • • 發佈:2018-12-16
-
1. 使用resultMap配置一對一對映
除了使用Mybatis的自動對映處理一對一巢狀外,還可以在XML對映檔案中配置結果對映。以下例子是用resultMap配置來處理上一節一對一對映的。
-
在SysUserMapper.xml中增加以下resultMap
<!-- 使用resultMap配置一對一對映(原始版) --> <resultMap id="userRoleMap" type="ex.mybatis.rbac.model.SysUser"> <id column="id" property="id" /> <result column="user_name" property="userName" /> <result column="user_password" property="userPassword" /> <result column="user_email" property="userEmail" /> <result column="create_time" jdbcType="TIMESTAMP" property="createTime" /> <result column="user_info" property="userInfo" /> <result column="head_img" jdbcType="BLOB" property="headImg" /> <!-- role相關屬性,為了避免不同表有相同的列,所有可能重名的都加上字首r_ --> <result column="r_id" property="role.id" /> <result column="role_name" property="role.roleName" /> <result column="enabled" property="role.enabled" /> <result column="create_by" property="role.createBy" /> <result column="r_create_time" jdbcType="TIMESTAMP" property="role.createTime" /> </resultMap>
這種配置和上一節相似的地方在於role的property配置部分使用了“role.”字首。在column部分,為了避免不同表中存在相同的列,所有可能重複的列都加上了r_字首。使用這種配置時,還需要修改SQL語句。繼續在XML中增加selectUserAndRoleById2方法,如下:
<!-- 假設一個使用者只有一個角色(使用resultMap配置一對一對映) 注意:resultMap中列為避免重複起的別名,需要與SQL中別名一樣,否則結果對映為空 --> <select id="selectUserAndRoleById2" resultMap="userRoleMap"> select u.id, u.user_name, u.user_password, u.user_email, u.create_time, u.user_info, u.head_img, r.id r_id, r.role_name, r.enabled, r.create_by, r.create_time r_create_time from sys_user u inner join sys_user_role ur on u.id = ur.user_id inner join sys_role r on ur.role_id = r.id where u.id = #{id} </select>
-
在SysUserMapper類中增加selectUserAndRoleById2方法
/**
* 假設一個使用者只有一個角色(使用resultMap配置一對一對映)
* @param id
* @return
*/
SysUser selectUserAndRoleById2(Long id);
-
在UserMaperTest類中增加對應的測試方法,如下:
@Test public void testSelectUserAndRoleById2() { // 獲取SqlSession SqlSession sqlSession = openSession(); try { // 獲取SysUserMapper介面 SysUserMapper userMapper = sqlSession.getMapper(SysUserMapper.class); // 呼叫selectUserAndRoleById2方法 SysUser user = userMapper.selectUserAndRoleById2(1001L); // user不為空 Assert.assertNotNull(user); System.out.println(user.getRole()); // role不為空 Assert.assertNotNull(user.getRole()); System.out.println(); } finally { sqlSession.close(); } }
-
執行結果
[ex.mybatis.rbac.mapper.SysUserMapper.selectUserAndRoleById2] - ==> Preparing: select u.id, u.user_name, u.user_password, u.user_email, u.create_time, u.user_info, u.head_img, r.id r_id, r.role_name, r.enabled, r.create_by, r.create_time r_create_time from sys_user u inner join sys_user_role ur on u.id = ur.user_id inner join sys_role r on ur.role_id = r.id where u.id = ?
[ex.mybatis.rbac.mapper.SysUserMapper.selectUserAndRoleById2] - ==> Parameters: 1001(Long)
[ex.mybatis.rbac.mapper.SysUserMapper.selectUserAndRoleById2] - <== Columns: id, user_name, user_password, user_email, create_time, user_info, head_img, r_id, role_name, enabled, create_by, r_create_time
[ex.mybatis.rbac.mapper.SysUserMapper.selectUserAndRoleById2] - <== Row: 1001, test, 123456, [email protected], 2018-10-02 17:17:11.0, <<BLOB>>, <<BLOB>>, 2, 普通使用者, 0, 1, 2018-10-01 18:27:37.0
[ex.mybatis.rbac.mapper.SysUserMapper.selectUserAndRoleById2] - <== Total: 1
SysRole [id=2, roleName=普通使用者, enabled=disabled, createBy=1, createTime=Mon Oct 01 18:27:37 CST 2018]
-
2. 使用resultMap繼承配置一對一對映
用過上一種寫法後,發現resultMap非常煩瑣,不但沒有方便使用,反而增加了工作量。為了簡化這種煩瑣的配置,Mybatis提供了resultMap繼承功能。以下例子是用Mybatis的resultMap繼承功能簡化上面的resultMap配置。因為Mybatis程式碼生成器會生成一個基本的resultMap,所以直接繼承,在SysUserMapper.xml中增加userRoleMap2如下:
<!-- 使用resultMap配置一對一對映(使用resultMap繼承配置) -->
<resultMap id="userRoleMap2" extends="userMap" type="ex.mybatis.rbac.model.SysUser">
<!-- role相關屬性,為了避免不同表有相同的列,所有可能重名的都加上字首r_ -->
<result column="r_id" property="role.id" />
<result column="role_name" property="role.roleName" />
<result column="enabled" property="role.enabled" />
<result column="create_by" property="role.createBy" />
<result column="r_create_time" jdbcType="TIMESTAMP" property="role.createTime" />
</resultMap>
使用了繼承後配置簡單了,而且對主表userMap需要修改時,只改一個地方就可以了。把selectUserAndRoleById2方法的resultMap替換為userRoleMap2,其它地方不用改,測試結果與上面一樣,配置如下:
<!-- 假設一個使用者只有一個角色(使用resultMap配置一對一對映)
注意:resultMap中列為避免重複起的別名,需要與SQL中別名一樣,否則結果對映為空
-->
<select id="selectUserAndRoleById2" resultMap="userRoleMap2">
select
u.id,
u.user_name,
u.user_password,
u.user_email,
u.create_time,
u.user_info,
u.head_img,
r.id r_id,
r.role_name,
r.enabled,
r.create_by,
r.create_time
r_create_time
from sys_user u
inner join sys_user_role ur on u.id = ur.user_id
inner join sys_role r on ur.role_id = r.id
where u.id = #{id}
</select>
-
3. 使用resultMap的
<association>
標籤配置一對一對映
在resultMap中,
<association>
標籤用於與一個複雜型別進行關聯。即用於一對一的關聯配置。
<association>
標籤的關聯配置用到以下屬性:
property:對應實體類中的屬性名,必填項。
javaType:屬性對應的型別。
resultMap:可以直接使用現有的resultMap,面不需要再配置。
columnPrefix:查詢列的字首,配置字首後,在子標籤配置
<result>
的column時可省略字首。
- 在SysUserMapper.xml中增加userRoleMap3
<!-- 使用resultMap的association標籤配置一對一對映 -->
<resultMap id="userRoleMap3" extends="userMap" type="ex.mybatis.rbac.model.SysUser">
<!-- role相關屬性,字首都加上了r_ -->
<association property="role" columnPrefix="r_" javaType="ex.mybatis.rbac.model.SysRole">
<result column="id" property="id" />
<result column="role_name" property="roleName" />
<result column="enabled" property="enabled" />
<result column="create_by" property="createBy" />
<result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
</association>
</resultMap>
- 因為列名全加上了r_字首,所以要修改SQL,因些增加selectUserAndRoleById3方法,如下:
<!-- 使用resultMap的association標籤配置一對一對映 -->
<select id="selectUserAndRoleById3" resultMap="userRoleMap3">
select
u.id,
u.user_name,
u.user_password,
u.user_email,
u.create_time,
u.user_info,
u.head_img,
r.id r_id,
r.role_name r_role_name,
r.enabled r_enabled,
r.create_by r_create_by,
r.create_time r_create_time
from sys_user u
inner join sys_user_role ur on u.id = ur.user_id
inner join sys_role r on ur.role_id = r.id
where u.id = #{id}
</select>
- 在SysUserMapper類增加selectUserAndRoleById3方法,如下:
/**
* 假設一個使用者只有一個角色(使用resultMap的association標籤配置一對一對映)
* @param id
* @return
*/
SysUser selectUserAndRoleById3(Long id);
- 測試結果
[ex.mybatis.rbac.mapper.SysUserMapper.selectUserAndRoleById3] - ==> Preparing: select u.id, u.user_name, u.user_password, u.user_email, u.create_time, u.user_info, u.head_img, r.id r_id, r.role_name r_role_name, r.enabled r_enabled, r.create_by r_create_by, r.create_time r_create_time from sys_user u inner join sys_user_role ur on u.id = ur.user_id inner join sys_role r on ur.role_id = r.id where u.id = ?
[ex.mybatis.rbac.mapper.SysUserMapper.selectUserAndRoleById3] - ==> Parameters: 1001(Long)
[ex.mybatis.rbac.mapper.SysUserMapper.selectUserAndRoleById3] - <== Columns: id, user_name, user_password, user_email, create_time, user_info, head_img, r_id, r_role_name, r_enabled, r_create_by, r_create_time
[ex.mybatis.rbac.mapper.SysUserMapper.selectUserAndRoleById3] - <== Row: 1001, test, 123456, [email protected], 2018-10-02 17:17:11.0, <<BLOB>>, <<BLOB>>, 2, 普通使用者, 0, 1, 2018-10-01 18:27:37.0
[ex.mybatis.rbac.mapper.SysUserMapper.selectUserAndRoleById3] - <== Total: 1
SysRole [id=2, roleName=普通使用者, enabled=disabled, createBy=1, createTime=Mon Oct 01 18:27:37 CST 2018]
<association>
標籤支援直接引用其它地方的resultMap,因些到這裡,resultMap還可以再簡化。如下為最簡版,專案中應當這樣用。
<!-- 使用resultMap的association標籤配置一對一對映(最簡版) -->
<resultMap id="userRoleMap4" extends="userMap" type="ex.mybatis.rbac.model.SysUser">
<!-- role相關屬性,直接通過resultMap屬性引用roleMap,需要加上名稱空間的字首,列字首都加上了r_ -->
<association property="role" columnPrefix="r_" resultMap="ex.mybatis.rbac.mapper.SysRoleMapper.roleMap" />
</resultMap>
- 把selectUserAndRoleById3方法的resultMap替換為userRoleMap4,其它地方不用改,測試結果與上面一樣。