如何在Spring Data MongoDB中关联Room与RoomType集合并通过Java Query实现?
在Spring Data MongoDB中用Query实现集合关联查询
对应你给出的SQL select * from Room r inner join RoomType rt on r.roomTypeId=rt._id,可以通过Spring Data MongoDB的**Aggregation(聚合)**结合$lookup操作来实现,以下是具体实现步骤:
1. 定义实体类
先创建与MongoDB集合对应的实体类,以及用于接收关联结果的DTO:
import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Document; import java.util.Date; // Room集合实体 @Document(collection = "Room") public class Room { @Id private String id; private String agentId; private String roomName; private String note; private String roomStatus; private String roomTypeId; // 关联RoomType的_id字段 private String createdBy; private Date createdAt; private String updatedBy; private Date updatedAt; private boolean isDeleted; // 生成Getters和Setters } // RoomType集合实体 @Document(collection = "RoomType") public class RoomType { @Id private String id; private String roomTypeName; private String note; private String createdBy; private Date createdAt; private String updatedBy; private Date updatedAt; private boolean isDeleted; // 生成Getters和Setters } // 关联结果DTO,用于封装Room和对应的RoomType数据 public class RoomWithTypeDTO { private Room room; private RoomType roomType; // 生成Getters和Setters }
2. 实现关联查询逻辑
使用MongoTemplate执行聚合操作,通过$lookup完成关联,再通过match过滤实现inner join效果:
import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.aggregation.Aggregation; import org.springframework.data.mongodb.core.aggregation.AggregationResults; import org.springframework.data.mongodb.core.aggregation.LookupOperation; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.stereotype.Service; import java.util.List; @Service public class RoomService { private final MongoTemplate mongoTemplate; // 构造注入MongoTemplate public RoomService(MongoTemplate mongoTemplate) { this.mongoTemplate = mongoTemplate; } public List<RoomWithTypeDTO> getRoomsJoinedWithType() { // 定义Lookup操作:关联RoomType集合 LookupOperation lookupRoomType = LookupOperation.newLookup() .from("RoomType") // 目标关联集合名 .localField("roomTypeId") // Room集合中的关联字段 .foreignField("_id") // RoomType集合中的匹配字段 .as("roomType"); // 关联结果的别名 // 构建聚合管道:先关联,再过滤掉未匹配到RoomType的记录(实现inner join) Aggregation aggregation = Aggregation.newAggregation( lookupRoomType, Aggregation.match(Criteria.where("roomType").size(1)) // 确保roomType数组有一条匹配数据 ); // 执行聚合查询,映射到DTO AggregationResults<RoomWithTypeDTO> results = mongoTemplate.aggregate( aggregation, "Room", RoomWithTypeDTO.class ); return results.getMappedResults(); } }
3. 关键说明
- MongoDB的
$lookup默认是**左连接(left join)**行为,会返回所有Room记录,即使没有匹配的RoomType;通过Aggregation.match(Criteria.where("roomType").size(1))可以过滤掉未匹配的记录,实现SQL中inner join的效果。 - 如果不需要严格的inner join,只需移除
match步骤即可得到左连接结果。 - 返回的
RoomWithTypeDTO中,roomType会自动映射为匹配的RoomType对象(因为我们指定了别名roomType,且DTO中对应字段名一致)。
内容的提问来源于stack exchange,提问作者Pnmtriet
相关产品推荐
相关产品推荐

