You need to enable JavaScript to run this app. Spring Boot集成MongoDB时findAll()返回空列表但集合存在文档
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot集成MongoDB时findAll()返回空列表但集合存在文档

问题场景
  • 基于Spring Boot开发的MongoDB对接应用,启动阶段数据库连接流程正常,无连接类异常
  • 调用MongoRepository提供的findAll()方法时,仓储层返回空列表,但目标集合中实际存在1条有效文档
  • 访问http://localhost:8080/api/v1/user/getAllUsers接口时,无异常堆栈抛出,仅输出流程埋点日志

涉及的代码定义:

仓储层

@Repository
public interface UserDao extends MongoRepository<User, String>{

}

服务层

@Component
@Slf4j
public class UserServiceImpl implements IUser {
    @Autowired
    UserDao userDao;

    @Override
    public List<User> getAllUsers() throws Exception {
        log.info("[ getAllUsers ] Start");
        List<User> response = new ArrayList<User>();

        try {
            log.debug("Calling user Dao to select all users");
            response = userDao.findAll();
        } catch (Exception e) {
            log.error(Constants.COMMENT_SELECTION_ERROR, e);
            throw new Exception(Constants.COMMENT_SELECTION_ERROR, e);
        }

        log.debug("Response: count of users :{} ", response.size());
        log.info("[ getAllUsers ] End :: Success");
        return response;
    }
}

控制器层

@RestController
@Slf4j
@SuppressWarnings("rawtypes")
@RequestMapping(value = "/api/v1/user")
public class UserApiController {

    @Autowired
    private IUser sUser;

    @ApiOperation(value = "getAllUsers", response = ResponseEntity.class)
    @ApiResponses(value = { 
        @ApiResponse(code = 200, message = "selection successful", response = User.class),
        @ApiResponse(code = 400, message = "Required parameter does not exist or is not in the expected format", response = User.class),
        @ApiResponse(code = 401, message = "You are not authorized to view the resource", response = User.class),
        @ApiResponse(code = 406, message = "The resource you were trying to reach is not found", response = User.class),
        @ApiResponse(code = 500, message = "Accessing the resource you were trying to reach is forbidden") 
    })
    @RequestMapping(value = "/getAllUsers", method = RequestMethod.GET, produces = "application/json")
    ResponseEntity<List<User>> getAllUsers() {
        log.info("[ getAllUsers ] Start");
        List<User> responseListUsers = new ArrayList<>();
        try {
            responseListUsers = sUser.getAllUsers();
            log.info("[ getAllUsers ] End :: Success");
            return new ResponseEntity<>(responseListUsers, HttpStatus.OK);
        } catch (Exception se) {
            log.error("[ getAllUsers ] End :: ERROR", se.getMessage());
            return new ResponseEntity<>(responseListUsers, HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }
}

实体模型

@ApiModel(value = "User", description = "User Model")
@Data
@Document
@NoArgsConstructor
public class User {
    String id;

    @ApiModelProperty(value = "name", required = true)
    @NotBlank
    private String name;

    @ApiModelProperty(value = "address", required = true)
    @NotBlank
    private String address;

    @ApiModelProperty(value = "phone", required = true)
    @NotNull
    @Pattern(regexp = Constants.PHONE_FORMAT)
    private String phone;

    @ApiModelProperty(value = "job", required = true)
    @NotBlank
    private String job;

    @ApiModelProperty(value = "agency", required = true)
    @DBRef
    private Agency agency;
}

目标集合中的文档结构参考:
User document

接口返回时无异常输出,日志仅包含流程埋点:

2021-03-31 15:51:51.023 INFO 19804 --- [nio-8080-exec-1] c.c.airbnb.controller.UserApiController : [ getAllUsers ] Start
2021-03-31 15:51:51.025 INFO 19804 --- [nio-8080-exec-1] c.c.airbnb.service.impl.UserServiceImpl : [ getAllUsers ] Start
2021-03-31 15:51:51.035 INFO 19804 --- [nio-8080-exec-1] c.c.airbnb.service.impl.UserServiceImpl : [ getAllUsers ] End :: Success
2021-03-31 15:51:51.037 INFO 19804 --- [nio-8080-exec-1] c.c.airbnb.controller.UserApiController : [ getAllUsers ] End :: Success

核心排查方向与解决方案

1. 集合名大小写不匹配(最高发问题)

  • Spring Data MongoDB 对未手动指定集合名的@Document实体,默认的集合名映射规则是类名首字母小写,即User实体默认查询的集合是user
  • MongoDB 原生对集合名大小写敏感,如果实际存储文档的集合名是大写开头的User,查询时会因为集合名不匹配直接返回空结果,全程无异常抛出
  • 解决方案:在实体类的@Document注解上手动指定和实际存储完全一致的集合名,比如:
    @Document(collection = "实际存储的集合准确名称")
    public class User {
      // 字段定义
    }
    

2. 连接的数据库名和实际存数库不匹配

  • 校验MongoDB连接串中的/后跟随的数据库名,是否和你查看文档所在的数据库完全一致
  • 这类问题常见于使用可视化工具查看数据时,误将其他同名库下的集合当成了目标库,应用实际连接的是另一个空数据库,连接过程正常但查询结果为空

3. @DBRef字段的静默解析过滤

  • 实体类中关联的Agency字段标注了@DBRef,要求MongoDB中存储的文档对应的agency字段必须是标准DBRef结构(包含$ref、$id属性)
  • 部分Spring Data MongoDB版本遇到字段结构不符合DBRef要求时,不会抛出解析异常,而是直接将该文档从返回结果中过滤,最终导致查询返回空列表
  • 校验方法:临时去掉agency字段的@DBRef注解,或简化实体类只保留id、name等基础字段,重新调用接口测试,如果能查到数据,就是DBRef字段的结构不匹配导致的问题,调整文档中的agency字段结构即可

4. 开启查询日志校验实际执行语句

  • 在配置文件中开启MongoDB查询的DEBUG日志,定位实际执行的查询目标:
    logging:
      level:
        org.springframework.data.mongodb.core.MongoTemplate: DEBUG
    
  • 调用接口后,将日志打印的查询语句(目标库、目标集合、过滤条件)直接放到MongoDB Shell或可视化工具中执行,对比返回结果和应用返回结果的差异,就能快速定位不匹配的环节

内容的提问来源于stack exchange,提问作者bretondev

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.27 11:45:02