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.总结
优点:
- 灵活性高:
@Result
注解可以根据需要自定义结果映射,允许开发人员根据实际情况灵活地配置映射关系,满足不同的需求。 - 易于理解和维护:通过在代码中直接定义结果映射关系,可以使代码更加清晰易读,易于理解和维护。
- 支持自定义类型处理器:
@Result
注解允许开发人员指定类型处理器,可以自定义处理查询结果的转换逻辑,提高灵活性和扩展性。
缺点:
- 繁琐:对于复杂的结果映射关系,需要在代码中编写大量的
@Result
注解,映射关系较多时会显得冗长繁琐。 - 容易出错:手动编写结果映射关系容易出错,例如属性名或列名拼写错误、类型处理器配置错误等,容易引发运行时异常或查询结果错误。
- 不利于维护:当数据库表结构发生变化时,需要手动修改代码中的结果映射配置,维护成本较高。