6.1 高级结果映射

6.1.1 一对一映射

6.1.1.1 使用自动映射处理一对一关系

image.png
在mapper接口中定义方法:
image.png
编写xml
image.png

6.1.1.2 使用resultMap配置一对一映射

image.png
image.png
还可以通过extends简化代码
image.png

6.1.1.3 使用resultMap的association标签配置一对一映射

在上面的配置上在做修改:

  1. <resultMap id="userRoleMap" type="com.ql.simple.model.SysUser" extends="userMap">
  2. <association property="role" columnPrefix="role_" javaType="com.ql.simple.model.SysRole">
  3. <result property="id" column="role_id"/>
  4. <result property="roleName" column="role_name"/>
  5. <result property="enabled" column="enabled"/>
  6. <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
  7. <result property="createBy" column="create_by"/>
  8. </association>
  9. </resultMap>

association标签的属性:

  • property:对应实体类中的属性名
  • javaType:属性对应的Java类型
  • resultType
  • resultMap
  • columnPrefix


由于配置了columnPrefix=”role“,在写sql的时候,sys_role表相关的查询列的别名都要有“role”前缀,在内部result配置column时,需要配置成去掉前缀的列名
image.png

6.1.1.4 association标签嵌套查询

  1. <resultMap id="userRoleMapSelect" type="com.ql.simple.model.SysUser" extends="userMap">
  2. <association property="role" column="{id=role_id}" select="com.ql.simple.mapper.RoleMapper.selectRoleById"></association>
  3. </resultMap>
  4. <select id="selectUserAndRoleByIdSelect" resultMap="userRoleMapSelect">
  5. select u.id,
  6. u.user_name,
  7. u.user_password,
  8. u.user_email,
  9. u.user_info,
  10. u.head_img,
  11. u.create_time,
  12. ur.role_id
  13. from sys_user u
  14. inner join sys_user_role ur on u.id = ur.user_id
  15. where u.id = #{id}
  16. </select>
  1. <resultMap id="roleMap" type="com.ql.simple.model.SysRole">
  2. <id property="id" column="id"/>
  3. <result property="roleName" column="role_name"/>
  4. <result property="enabled" column="enabled"/>
  5. <result property="createBy" column="create_by"/>
  6. <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
  7. </resultMap>
  8. <select id="selectRoleById" resultMap="roleMap">
  9. select * from sys_role where id = #{id}
  10. </select>

开启延迟加载:
image.png
这样只有在调用getRole的时候才会执行关于role的查询:
image.png
但根据debug发现并不是预想的那样,是因为mybatis的全局配置中有个参数为aggressiveLazyLoading,该参数默认为true,含义是,对任意延迟属性的调用会使带有延迟加载属性的对象完整加载,反之,每种属性都将按需加载
image.png
mybatis还有个参数lazyLoadTriggerMethods,当调用配置中的方法时,加载全部的延迟加载数据,默认值为“equals,clone,hashCode,toString”因此在默认情况下,只要调用其中一个方法就可以实现加载调用对象的全部数据

6.1.2 一对多映射

6.1.2.1 collection集合的嵌套结果映射

先对SysUser类进行修改:

  1. /** 用户表
  2. * Created by ql on 2022/6/9
  3. */
  4. @Data
  5. public class SysUser {
  6. private Long id;
  7. private String userName;
  8. private String userPassword;
  9. private String userEmail;
  10. private String userInfo;
  11. private byte[] headImg;
  12. private Date createTime;
  13. // private SysRole role;
  14. private List<SysRole> roleList;
  15. }

修改UserMapper.xml

  1. <resultMap id="userRoleListMap" type="com.ql.simple.model.SysUser" extends="userMap">
  2. <collection property="roleList" columnPrefix="role_" resultMap="com.ql.simple.mapper.RoleMapper.roleMap">
  3. </collection>
  4. </resultMap>

业务逻辑:

  1. /**
  2. * 获取所有的用户以及对应的所有角色
  3. * @return
  4. */
  5. List<SysUser> selectAllUserAndRoles();
  1. <select id="selectAllUserAndRoles" resultMap="userRoleListMap">
  2. select u.id,
  3. u.user_name,
  4. u.user_password,
  5. u.user_email,
  6. u.user_info,
  7. u.head_img,
  8. u.create_time,
  9. r.id role_id,
  10. r.role_name role_role_name,
  11. r.enabled role_enabled,
  12. r.create_by role_create_by,
  13. r.create_time role_create_time
  14. from sys_user u
  15. inner join sys_user_role ur on u.id = ur.user_id
  16. inner join sys_role r on ur.role_id = r.id
  17. </select>

6.1.2.2 collection集合的嵌套查询

6.1.3 鉴别器映射

  1. <resultMap id="rolePrivilegeListMapChoose" type="com.ql.simple.model.SysRole">
  2. <discriminator javaType="int" column="enabled">
  3. <case value="1" resultMap="rolePrivilegeListMapSelect"></case>
  4. <case value="0" resultMap="roleMap"></case>
  5. </discriminator>
  6. </resultMap>

当enable为1的时候表示可用,这时使用rolePrivilegeListMapSelect映射,这是一个一对多的嵌套查询映射,可以获取到该角色下详细的权限信息
当角色被禁用时,只能获取角色的基本信息,不能获得角色的权限信息

  1. <select id="selectRoleByUserIdChoose" resultMap="rolePrivilegeListMapChoose">
  2. select r.id,
  3. r.role_name,
  4. r.enabled,
  5. r.create_by,
  6. r.create_time
  7. from sys_role r
  8. inner join sys_user_role ur on ur.role_id = r.id
  9. where ur.user_id = #{userId}
  10. </select>

6.2 存储过程

6.2.1 第一个存储过程

  1. <select id="selectUserById" statementType="CALLABLE" useCache="false">
  2. {call select_user_by_id(
  3. #{id,mode=IN},
  4. #{userName,mode=OUT,jdbcType=VARCHAR},
  5. #{userPassword,mode=OUT,jdbcType=VARCHAR},
  6. #{userEmail,mode=OUT,jdbcType=VARCHAR},
  7. #{userInfo,mode=OUT,jdbcType=VARCHAR},
  8. #{headImg,mode=OUT,jdbcType=BLOB,javaType=_byte[]},
  9. #{createTime,mode=OUT,jdbcType=TIMESTAMP}
  10. )}
  11. </select>
  1. /**
  2. * 使用存储过程查询用户信息
  3. * @param user
  4. */
  5. void selectUserById(SysUser user);
  • 需要把statementType设置为CALLABLE,由于存储过程方式不支持MyBatis的二级缓存,因此为了避免缓存配置出错,直接将select标签的useCache属性设置为false
  • 必须指定参数的mode,可以为IN、OUT、INOUT
  • _byte表示的基本类型,Mybatis默认使用的是Byte类型

    6.2.2 第二个存储过程

    1. <select id="selectUserPage" statementType="CALLABLE" useCache="false" resultMap="userMap">
    2. {
    3. call select_user_page(
    4. #{userName,mode=IN},
    5. #{offset,mode=IN},
    6. #{limit,mode=IN},
    7. #{total,mode=OUT,jdbcType=BIGINT}
    8. )
    9. }
    10. </select>
    1. /**
    2. * 使用存储过程分页查询
    3. * @param params
    4. * @return
    5. */
    6. List<SysUser> selectUserPage(Map<String, Object> params);

    使用Map类型接受返回值
    测试代码:
    image.png
    image.png

    6.2.3 第三个和第四个存储过程

    1. /**
    2. * 保存用户信息和角色关联信息
    3. * @param user
    4. * @param roleIds
    5. * @return
    6. */
    7. int insertUserAndRoles(@Param("user") SysUser user, @Param("roleIds") String roleIds);
    8. /**
    9. * 根据用户id删除用户和用户的角色信息
    10. * @param id
    11. * @return
    12. */
    13. int deleteUserById(Long id);
    1. <insert id="insertUserAndRoles" statementType="CALLABLE">
    2. {
    3. call insert_user_and_roles(
    4. #{user.id,mode=OUT,jdbcType=BIGINT},
    5. #{user.userName,mode=IN},
    6. #{user.userPassword,mode=IN},
    7. #{user.userEmail,mode=IN},
    8. #{user.userInfo,mode=IN},
    9. #{user.headImg,mode=IN,jdbcType=BLOB},
    10. #{user.createTime,mode=OUT,jdbcType=TIMESTAMP},
    11. #{roleIds,mode=IN}
    12. )
    13. }
    14. </insert>
    15. <delete id="deleteUserById" statementType="CALLABLE">
    16. {call delete_user_by_id(#{id,mode=IN})}
    17. </delete>

    6.3 使用枚举或其他对象

    6.3.1 使用Mybatis提供的枚举处理器

    1. /**
    2. * Created by ql on 2022/6/14
    3. */
    4. public enum Enabled {
    5. disabled,
    6. enabled
    7. }

    image.png
    还得在mybatis-config中配置:

    1. <typeHandlers>
    2. <typeHandler javaType="com.ql.simple.type.Enabled" handler="org.apache.ibatis.type.EnumOrdinalTypeHandler"/>
    3. </typeHandlers>

    6.3.2 使用自定义的类型处理器

    1. public enum Enabled {
    2. disabled(1),
    3. enabled(0);
    4. private final int value;
    5. private Enabled(int value) {
    6. this.value = value;
    7. }
    8. public int getValue() {
    9. return value;
    10. }
    11. }
    1. /**
    2. * Created by ql on 2022/6/14
    3. */
    4. public class EnabledTypeHandler implements TypeHandler<Enabled> {
    5. private final Map<Integer, Enabled> enabledMap = new HashMap<Integer, Enabled>();
    6. public EnabledTypeHandler() {
    7. for (Enabled enabled : Enabled.values()) {
    8. enabledMap.put(enabled.getValue(), enabled);
    9. }
    10. }
    11. @Override
    12. public void setParameter(PreparedStatement preparedStatement, int i, Enabled enabled, JdbcType jdbcType) throws SQLException {
    13. preparedStatement.setInt(i, enabled.getValue());
    14. }
    15. @Override
    16. public Enabled getResult(ResultSet resultSet, String s) throws SQLException {
    17. int value = resultSet.getInt(s);
    18. return enabledMap.get(value);
    19. }
    20. @Override
    21. public Enabled getResult(ResultSet resultSet, int i) throws SQLException {
    22. int value = resultSet.getInt(i);
    23. return enabledMap.get(value);
    24. }
    25. @Override
    26. public Enabled getResult(CallableStatement callableStatement, int i) throws SQLException {
    27. int value = callableStatement.getInt(i);
    28. return enabledMap.get(value);
    29. }
    30. }

    6.3.3 对Java8日期的支持

    1. <dependency>
    2. <groupId>org.mybatis</groupId>
    3. <artifactId>mybatis-typehandlers-jsr310</artifactId>
    4. <version>1.0.2</version>
    5. </dependency>