如何在MyBatis嵌套查询集合时用Role实体传参?解决DEL_NOT空指针异常
Hey there! Let's tackle your two MyBatis questions step by step— I’ve run into similar scenarios before, so I’ll share practical solutions based on real-world usage.
1. 如何在MyBatis中针对集合的列属性使用嵌套查询,并接收实体作为参数?
MyBatis的<collection>标签正是用来处理集合类型属性的嵌套查询的,结合实体参数传递的核心是明确参数的传递路径和Mapper接口的定义。这里给你一个具体的示例:
示例场景
假设我们有两个实体:User(包含List<Role>角色集合)和Role,我们需要通过Role实体作为参数,查询关联的用户列表,并嵌套加载用户的角色信息。
实体类定义
// Role.java public class Role { private Long id; private String roleName; // 其他业务属性 + getter/setter } // User.java public class User { private Long id; private String username; private List<Role> roles; // 集合属性,需要嵌套查询 // getter/setter }
Mapper接口定义
// UserMapper.java public interface UserMapper { // 接收Role实体作为参数,查询关联用户并嵌套加载角色 List<User> listUsersByRole(Role role); } // RoleMapper.java public interface RoleMapper { // 嵌套查询:根据用户ID和Role实体的条件,查询用户的角色列表 List<Role> getRolesByUserAndRole(@Param("userId") Long userId, @Param("role") Role role); }
Mapper XML配置
<!-- UserMapper.xml --> <select id="listUsersByRole" resultMap="UserWithRolesResultMap"> SELECT id, username FROM user WHERE role_type = #{roleName} <!-- 直接引用Role实体的属性,MyBatis会自动识别 --> AND del_flag = ${com.your.package.Constants.DEL_NOT} </select> <resultMap id="UserWithRolesResultMap" type="User"> <id property="id" column="id"/> <result property="username" column="username"/> <!-- 集合嵌套查询:调用RoleMapper的方法,传递用户ID和Role实体参数 --> <collection property="roles" ofType="Role" select="com.your.package.RoleMapper.getRolesByUserAndRole" column="{userId=id, role=role}" <!-- 传递主查询的列和实体参数 --> /> </resultMap> <!-- RoleMapper.xml --> <select id="getRolesByUserAndRole" resultType="Role"> SELECT id, role_name FROM role WHERE user_id = #{userId} AND role_status = #{role.status} <!-- 引用传递过来的Role实体属性 --> AND del_flag = ${com.your.package.Constants.DEL_NOT} </select>
关键要点
- 当接口方法只接收一个实体参数时,MyBatis允许直接通过
#{属性名}引用实体的属性。 <collection>的column属性支持多参数传递,格式为{参数名1=列名1, 参数名2=参数名2},这里的role=role是把主查询接收的Role实体传递给嵌套查询。- 嵌套查询的接口方法可以用
@Param注解明确参数名,避免混淆。
2. 解决listByRole方法传递Role实体时出现的DEL_NOT常量为空异常
这个异常通常是因为常量的引用方式错误或者实体属性与XML参数不匹配导致的,我们可以按以下步骤排查:
步骤1:检查DEL_NOT常量的定义与引用
首先确认你的DEL_NOT是全局常量(比如在Constants类中)还是Role实体的属性:
如果是全局静态常量:
public class Constants { // 确保是public static final,且赋值正确 public static final String DEL_NOT = "0"; }在XML中必须用
${}引用(因为#{}是预编译参数,会把DEL_NOT当作实体属性查找):<!-- 正确写法:引用全局静态常量 --> WHERE del_flag = ${com.your.package.Constants.DEL_NOT} <!-- 错误写法:会导致MyBatis在Role实体中查找DEL_NOT属性,找不到就为空 --> WHERE del_flag = #{DEL_NOT}如果
DEL_NOT是Role实体的属性:
确保实体中有对应的属性和getter方法,且XML中的参数名与属性名匹配(开启驼峰映射的话,数据库列del_not对应实体delNot):public class Role { private String delNot; // 对应数据库del_not // getter/setter }XML中引用:
WHERE del_flag = #{delNot}
步骤2:检查实体参数的传递是否正确
确保listByRole方法的定义正确,且XML中没有错误引用不存在的属性:
// 正确的接口定义 List<User> listByRole(Role role);
XML中引用实体属性时,直接用#{属性名}即可,不需要额外前缀(单个实体参数时MyBatis会自动处理)。
步骤3:检查MyBatis配置
如果开启了驼峰命名自动映射,确保实体属性名和数据库列名的映射正确:
<!-- mybatis-config.xml或application.yml中的配置 --> <settings> <setting name="mapUnderscoreToCamelCase" value="true"/> </settings>
内容的提问来源于stack exchange,提问作者Paosin

