我无法使用嵌套 Java 记录进行 hibernate citeria 查询,因为: 原因:org.postgresql.util.PSQLException:错误:“.”处的语法错误
我将Java记录定义如下:
public record RoomRecord(Long id, String identifier, int bedsNumber, int Set<BedRecord> beds) {
public record BedRecord(Long id, String identifier, Integer position) {}
}
以下是我的条件查询:
CriteriaBuilder builder = getCriteriaBuilder();
CriteriaQuery<RoomRecord> criteria = builder.createQuery(RoomRecord.class).distinct(true);
Root<Room> root = criteria.from(Room.class);
criteria.where(builder.equal(root.get(Room_.organization), organization));
criteria.select(builder.construct(RoomRecord.class, root.get(Room_.id), root.get(Room_.identifier), root.get(Room_.floor), root.get(Room_.bedsNumber),
root.get(Room_.virtualBedsNumber), root.get(Room_.beds)));`
您遇到的问题源于 Hibernate(以及一般的 JPA)不完全支持嵌套 Java 记录,特别是在尝试映射 RoomRecord 中的 Set 之类的嵌套关系时。 Hibernate 可能正在努力构建嵌套结构 Room_.beds 的查询,该结构表示为 Set。
解决方案:正确映射嵌套Set
例如:
CriteriaBuilder builder = getCriteriaBuilder();
// Query for Room entity
CriteriaQuery<Tuple> roomCriteria = builder.createTupleQuery();
Root<Room> roomRoot = roomCriteria.from(Room.class);
roomCriteria.multiselect(
roomRoot.get(Room_.id),
roomRoot.get(Room_.identifier),
roomRoot.get(Room_.bedsNumber)
);
roomCriteria.where(builder.equal(roomRoot.get(Room_.organization), organization));
// Execute query and map results to RoomRecord
List<Tuple> rooms = entityManager.createQuery(roomCriteria).getResultList();
List<RoomRecord> roomRecords = rooms.stream()
.map(tuple -> {
Long roomId = tuple.get(0, Long.class);
// Fetch nested beds for the room
CriteriaQuery<Bed> bedCriteria = builder.createQuery(Bed.class);
Root<Bed> bedRoot = bedCriteria.from(Bed.class);
bedCriteria.where(builder.equal(bedRoot.get(Bed_.room), roomId));
List<Bed> beds = entityManager.createQuery(bedCriteria).getResultList();
Set<RoomRecord.BedRecord> bedRecords = beds.stream()
.map(bed -> new RoomRecord.BedRecord(bed.getId(), bed.getIdentifier(), bed.getPosition()))
.collect(Collectors.toSet());
return new RoomRecord(
roomId,
tuple.get(1, String.class),
tuple.get(2, Integer.class),
bedRecords
);
})
.collect(Collectors.toList());