You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在MyBatis嵌套查询集合时用Role实体传参?解决DEL_NOT空指针异常

解决MyBatis集合嵌套查询与实体参数传递的问题

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 03:32:37