mybatis的@Result注解处理复杂的结果映射

1.@Result注解概述

        @Result 是 MyBatis 中用于结果映射的注解之一,它用于指定查询结果中的列与 Java 对象属性之间的映射关系。

        通常与@Results一起使用

    @Results({
            @Result(property = "menuIds", column = "menuIds", javaType = List.class, typeHandler = MenuIdsTypeHandler.class)
    })
    @Select("SELECT r.role_id AS roleId,r.p_id AS pId,r.role_name AS roleName," +
            "    r.description,r.scope,r.sort,r.remark,\n" +
            "    GROUP_CONCAT(DISTINCT CONCAT(m.menu_id,'_', m.menu_type)) AS menuIds,\n" +
            "FROM role r \n" +
            "LEFT JOIN role_menu rm ON r.role_id = rm.role_id \n" +
            "LEFT JOIN menu m ON rm.menu_id = m.menu_id \n" +
            "GROUP BY r.role_id, r.p_id, r.role_name, r.description, r.scope, r.sort, r.remark \n" +
            "ORDER BY r.sort")
    List<SysRoleVO> pageRoleByCondition();
  • 上面的示例就是将角色绑定的菜单id与菜单类型组合成的id-type类的字符串处理为对象列表
  • property: 指定 Java 对象中的属性名,表示将查询结果中的列映射到该属性上。
  • column: 指定查询结果集中的列名,表示要映射的数据库列名。
  • javaType: 指定 Java 对象属性的类型,可以是任何有效的 Java 类型,例如 String.class、Integer.class、List.class 等。
  • typeHandler: 指定类型处理器,用于处理查询结果值并将其转换为指定的 Java 类型。

2.类型处理器的编写 

package com.lw.acoustic.web.common.utils.mysql;

import com.lw.acoustic.system.vo.MenuIdTypePair;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class MenuIdsTypeHandler extends BaseTypeHandler<List<MenuIdTypePair>> {

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, List<MenuIdTypePair> parameter, JdbcType jdbcType)
            throws SQLException {
        // 这个方法用于设置 PreparedStatement 的参数,一般不需要实现
    }

    @Override
    public List<MenuIdTypePair> getNullableResult(ResultSet rs, String columnName) throws SQLException {
        return parseResultSet(rs.getString(columnName));
    }

    @Override
    public List<MenuIdTypePair> getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        return parseResultSet(rs.getString(columnIndex));
    }

    @Override
    public List<MenuIdTypePair> getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        return parseResultSet(cs.getString(columnIndex));
    }

    private List<MenuIdTypePair> parseResultSet(String result) {
        List<MenuIdTypePair> menuIdTypePairs = new ArrayList<>();
        if (result != null) {
            String[] pairs = result.split(",");
            for (String pair : pairs) {
                String[] values = pair.split("_");
                if (values.length == 2) {
                    Integer menuId = Integer.parseInt(values[0]);
                    Integer menuType = Integer.parseInt(values[1]);
                    MenuIdTypePair menuIdTypePair = new MenuIdTypePair(menuId, menuType);
                    menuIdTypePairs.add(menuIdTypePair);
                }
            }
        }
        return menuIdTypePairs;
    }
}
  • MenuIdsTypeHandler 类继承自 BaseTypeHandler<List<MenuIdTypePair>>,表示这是一个处理 List<MenuIdTypePair> 类型的自定义类型处理器。
  • getNullableResult 方法用于从 ResultSet 或 CallableStatement 中获取查询结果,并将其转换为 List<MenuIdTypePair> 对象。
  • parseResultSet 方法用于解析查询结果字符串,并将其转换为 List<MenuIdTypePair> 对象。在这个方法中,首先将字符串按逗号分割为一组键值对,然后遍历每个键值对,再将键值对按下划线分割为键和值。如果分割后的结果长度为2,则将键和值转换为整数,并创建 MenuIdTypePair 对象,最后将其添加到 menuIdTypePairs 列表中。

3.总结

优点:

  1. 灵活性高:@Result 注解可以根据需要自定义结果映射,允许开发人员根据实际情况灵活地配置映射关系,满足不同的需求。
  2. 易于理解和维护:通过在代码中直接定义结果映射关系,可以使代码更加清晰易读,易于理解和维护。
  3. 支持自定义类型处理器:@Result 注解允许开发人员指定类型处理器,可以自定义处理查询结果的转换逻辑,提高灵活性和扩展性。

缺点:

  1. 繁琐:对于复杂的结果映射关系,需要在代码中编写大量的 @Result 注解,映射关系较多时会显得冗长繁琐。
  2. 容易出错:手动编写结果映射关系容易出错,例如属性名或列名拼写错误、类型处理器配置错误等,容易引发运行时异常或查询结果错误。
  3. 不利于维护:当数据库表结构发生变化时,需要手动修改代码中的结果映射配置,维护成本较高。
  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值