6.1 高级结果映射
6.1.1 一对一映射
6.1.1.1 使用自动映射处理一对一关系
6.1.1.2 使用resultMap配置一对一映射
6.1.1.3 使用resultMap的association标签配置一对一映射
在上面的配置上在做修改:
<resultMap id="userRoleMap" type="com.ql.simple.model.SysUser" extends="userMap">
<association property="role" columnPrefix="role_" javaType="com.ql.simple.model.SysRole">
<result property="id" column="role_id"/>
<result property="roleName" column="role_name"/>
<result property="enabled" column="enabled"/>
<result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
<result property="createBy" column="create_by"/>
</association>
</resultMap>
association标签的属性:
- property:对应实体类中的属性名
- javaType:属性对应的Java类型
- resultType
- resultMap
- columnPrefix
…
由于配置了columnPrefix=”role“,在写sql的时候,sys_role表相关的查询列的别名都要有“role”前缀,在内部result配置column时,需要配置成去掉前缀的列名
6.1.1.4 association标签嵌套查询
<resultMap id="userRoleMapSelect" type="com.ql.simple.model.SysUser" extends="userMap">
<association property="role" column="{id=role_id}" select="com.ql.simple.mapper.RoleMapper.selectRoleById"></association>
</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
inner join sys_user_role ur on u.id = ur.user_id
where u.id = #{id}
</select>
<resultMap id="roleMap" type="com.ql.simple.model.SysRole">
<id property="id" column="id"/>
<result property="roleName" column="role_name"/>
<result property="enabled" column="enabled"/>
<result property="createBy" column="create_by"/>
<result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
</resultMap>
<select id="selectRoleById" resultMap="roleMap">
select * from sys_role where id = #{id}
</select>
开启延迟加载:
这样只有在调用getRole的时候才会执行关于role的查询:
但根据debug发现并不是预想的那样,是因为mybatis的全局配置中有个参数为aggressiveLazyLoading,该参数默认为true,含义是,对任意延迟属性的调用会使带有延迟加载属性的对象完整加载,反之,每种属性都将按需加载
mybatis还有个参数lazyLoadTriggerMethods,当调用配置中的方法时,加载全部的延迟加载数据,默认值为“equals,clone,hashCode,toString”因此在默认情况下,只要调用其中一个方法就可以实现加载调用对象的全部数据
6.1.2 一对多映射
6.1.2.1 collection集合的嵌套结果映射
先对SysUser类进行修改:
/** 用户表
* Created by ql on 2022/6/9
*/
@Data
public class SysUser {
private Long id;
private String userName;
private String userPassword;
private String userEmail;
private String userInfo;
private byte[] headImg;
private Date createTime;
// private SysRole role;
private List<SysRole> roleList;
}
修改UserMapper.xml
<resultMap id="userRoleListMap" type="com.ql.simple.model.SysUser" extends="userMap">
<collection property="roleList" columnPrefix="role_" resultMap="com.ql.simple.mapper.RoleMapper.roleMap">
</collection>
</resultMap>
业务逻辑:
/**
* 获取所有的用户以及对应的所有角色
* @return
*/
List<SysUser> selectAllUserAndRoles();
<select id="selectAllUserAndRoles" resultMap="userRoleListMap">
select u.id,
u.user_name,
u.user_password,
u.user_email,
u.user_info,
u.head_img,
u.create_time,
r.id role_id,
r.role_name role_role_name,
r.enabled role_enabled,
r.create_by role_create_by,
r.create_time role_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
</select>
6.1.2.2 collection集合的嵌套查询
6.1.3 鉴别器映射
<resultMap id="rolePrivilegeListMapChoose" type="com.ql.simple.model.SysRole">
<discriminator javaType="int" column="enabled">
<case value="1" resultMap="rolePrivilegeListMapSelect"></case>
<case value="0" resultMap="roleMap"></case>
</discriminator>
</resultMap>
当enable为1的时候表示可用,这时使用rolePrivilegeListMapSelect映射,这是一个一对多的嵌套查询映射,可以获取到该角色下详细的权限信息
当角色被禁用时,只能获取角色的基本信息,不能获得角色的权限信息
<select id="selectRoleByUserIdChoose" resultMap="rolePrivilegeListMapChoose">
select r.id,
r.role_name,
r.enabled,
r.create_by,
r.create_time
from sys_role r
inner join sys_user_role ur on ur.role_id = r.id
where ur.user_id = #{userId}
</select>
6.2 存储过程
6.2.1 第一个存储过程
<select id="selectUserById" statementType="CALLABLE" useCache="false">
{call select_user_by_id(
#{id,mode=IN},
#{userName,mode=OUT,jdbcType=VARCHAR},
#{userPassword,mode=OUT,jdbcType=VARCHAR},
#{userEmail,mode=OUT,jdbcType=VARCHAR},
#{userInfo,mode=OUT,jdbcType=VARCHAR},
#{headImg,mode=OUT,jdbcType=BLOB,javaType=_byte[]},
#{createTime,mode=OUT,jdbcType=TIMESTAMP}
)}
</select>
/**
* 使用存储过程查询用户信息
* @param user
*/
void selectUserById(SysUser user);
- 需要把statementType设置为CALLABLE,由于存储过程方式不支持MyBatis的二级缓存,因此为了避免缓存配置出错,直接将select标签的useCache属性设置为false
- 必须指定参数的mode,可以为IN、OUT、INOUT
_byte表示的基本类型,Mybatis默认使用的是Byte类型
6.2.2 第二个存储过程
<select id="selectUserPage" statementType="CALLABLE" useCache="false" resultMap="userMap">
{
call select_user_page(
#{userName,mode=IN},
#{offset,mode=IN},
#{limit,mode=IN},
#{total,mode=OUT,jdbcType=BIGINT}
)
}
</select>
/**
* 使用存储过程分页查询
* @param params
* @return
*/
List<SysUser> selectUserPage(Map<String, Object> params);
6.2.3 第三个和第四个存储过程
/**
* 保存用户信息和角色关联信息
* @param user
* @param roleIds
* @return
*/
int insertUserAndRoles(@Param("user") SysUser user, @Param("roleIds") String roleIds);
/**
* 根据用户id删除用户和用户的角色信息
* @param id
* @return
*/
int deleteUserById(Long id);
<insert id="insertUserAndRoles" statementType="CALLABLE">
{
call insert_user_and_roles(
#{user.id,mode=OUT,jdbcType=BIGINT},
#{user.userName,mode=IN},
#{user.userPassword,mode=IN},
#{user.userEmail,mode=IN},
#{user.userInfo,mode=IN},
#{user.headImg,mode=IN,jdbcType=BLOB},
#{user.createTime,mode=OUT,jdbcType=TIMESTAMP},
#{roleIds,mode=IN}
)
}
</insert>
<delete id="deleteUserById" statementType="CALLABLE">
{call delete_user_by_id(#{id,mode=IN})}
</delete>
6.3 使用枚举或其他对象
6.3.1 使用Mybatis提供的枚举处理器
/**
* Created by ql on 2022/6/14
*/
public enum Enabled {
disabled,
enabled
}
还得在mybatis-config中配置:<typeHandlers>
<typeHandler javaType="com.ql.simple.type.Enabled" handler="org.apache.ibatis.type.EnumOrdinalTypeHandler"/>
</typeHandlers>
6.3.2 使用自定义的类型处理器
public enum Enabled {
disabled(1),
enabled(0);
private final int value;
private Enabled(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
/**
* Created by ql on 2022/6/14
*/
public class EnabledTypeHandler implements TypeHandler<Enabled> {
private final Map<Integer, Enabled> enabledMap = new HashMap<Integer, Enabled>();
public EnabledTypeHandler() {
for (Enabled enabled : Enabled.values()) {
enabledMap.put(enabled.getValue(), enabled);
}
}
@Override
public void setParameter(PreparedStatement preparedStatement, int i, Enabled enabled, JdbcType jdbcType) throws SQLException {
preparedStatement.setInt(i, enabled.getValue());
}
@Override
public Enabled getResult(ResultSet resultSet, String s) throws SQLException {
int value = resultSet.getInt(s);
return enabledMap.get(value);
}
@Override
public Enabled getResult(ResultSet resultSet, int i) throws SQLException {
int value = resultSet.getInt(i);
return enabledMap.get(value);
}
@Override
public Enabled getResult(CallableStatement callableStatement, int i) throws SQLException {
int value = callableStatement.getInt(i);
return enabledMap.get(value);
}
}
6.3.3 对Java8日期的支持
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-typehandlers-jsr310</artifactId>
<version>1.0.2</version>
</dependency>