Spring Data MongoDB返回完整对象而非DBRef ID问题求助
问题描述
我使用Spring与MongoDB开发,定义了Folder实体类,其中包含子文件夹列表和笔记列表,通过@DBRef存储对象引用ID而非完整对象。但请求根文件夹时,API返回了所有嵌套的子文件夹及关联对象,获取到暂不需要的数据。我希望仅返回子文件夹ID,以便点击时通过ID发起HTTP GET请求按需加载。
Folder实体类代码
package org.example.schoolioapi.domain; import lombok.Data; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.DBRef; import org.springframework.data.mongodb.core.mapping.Document; import java.util.ArrayList; import java.util.List; @Document(collection = "folders") @Data public class Folder { @Id private String id; private String name; @DBRef private List<Folder> subFolders; @DBRef private List<Note> notes; public Folder(String name) { this.name = name; this.subFolders = new ArrayList<>(); this.notes = new ArrayList<>(); } public void addNote(Note note) { if (this.notes == null) notes = List.of(note); else notes.add(note); } public void addSubFolder(Folder subFolder) { if (this.subFolders == null) subFolders = List.of(subFolder); else subFolders.add(subFolder); } }
数据库中Folder对象示例

API返回结果

解决方案
方法一:使用DTO(数据传输对象)控制返回结构
@DBRef默认会自动解析关联对象并返回完整数据,最直接的方式是定义DTO剥离不需要的关联对象,只返回ID列表:
- 创建FolderDTO类
import lombok.Data; import java.util.List; @Data public class FolderDTO { private String id; private String name; private List<String> subFolderIds; private List<String> noteIds; }
- 实体转DTO的逻辑
在Service或Controller层,将Folder实体转换为DTO,提取关联对象的ID:
import java.util.stream.Collectors; public FolderDTO convertFolderToDTO(Folder folder) { FolderDTO dto = new FolderDTO(); dto.setId(folder.getId()); dto.setName(folder.getName()); // 提取子文件夹ID列表 dto.setSubFolderIds(folder.getSubFolders().stream() .map(Folder::getId) .collect(Collectors.toList())); // 提取笔记ID列表 dto.setNoteIds(folder.getNotes().stream() .map(Note::getId) .collect(Collectors.toList())); return dto; }
- 调整API返回类型
Controller方法返回FolderDTO而非原Folder实体:
@GetMapping("/folders/{id}") public ResponseEntity<FolderDTO> getFolderById(@PathVariable String id) { Folder folder = folderRepository.findById(id).orElseThrow(); FolderDTO dto = convertFolderToDTO(folder); return ResponseEntity.ok(dto); }
方法二:使用Spring Data Projection投影查询
通过定义投影接口,直接从数据库查询时只返回需要的字段和ID列表:
- 定义投影接口
import org.springframework.beans.factory.annotation.Value; import java.util.List; public interface FolderProjection { String getId(); String getName(); // 提取子文件夹ID列表 @Value("#{target.subFolders.![id]}") List<String> getSubFolderIds(); // 提取笔记ID列表 @Value("#{target.notes.![id]}") List<String> getNoteIds(); }
- Repository中使用投影查询
import org.springframework.data.mongodb.repository.MongoRepository; public interface FolderRepository extends MongoRepository<Folder, String> { FolderProjection findById(String id); }
- API直接返回投影结果
@GetMapping("/folders/{id}") public ResponseEntity<FolderProjection> getFolderById(@PathVariable String id) { FolderProjection projection = folderRepository.findById(id); return ResponseEntity.ok(projection); }
内容的提问来源于stack exchange,提问作者Vled
相关产品推荐
相关产品推荐

