WHERE 中的 JPQL 单个集合元素

JPQL single collection element in WHERE

我正在创建一个小型论坛。实体及其关系是这样的:

实体 TopicPostOneToMany 关系,PostUser

ManyToOne 关系

我想通过检查每个主题中第一个 post 的作者来获取一个特定用户的所有主题。这是我的 JPQL:

SELECT t FROM Topic t JOIN t.posts p WHERE p.user=:user

但是这个WHERE会检查topic中的所有post,我只想检查第一个post(这个用户会被认为是topic的作者)。

谢谢

只需使用本机查询,在连接时使用子 select,这样

@Query(value = "SELECT * FROM topics t JOIN posts p ON p.topic_id = (SELECT topic_id FROM posts p1 WHERE p1.topic_id = t.id ORDER BY p1.id ASC LIMIT 1) WHERE p.user_id = :userId", nativeQuery=true)
List<Topic> findTopicsByUser(@Param("userId") Long userId);

我在这里找到了更好的解决方案:Indexed element access in JPQL

基本上我可以用JPQL中的INDEX()来描述集合的索引:

SELECT t FROM Topic t JOIN t.posts p WHERE p.user = :user AND INDEX(p) = 0

为了使 INDEX() 工作,我需要在 Topic 实体的 posts 字段上添加一个 @OrderedColumn

@OrderColumn(name = "order_column")
@OneToMany(cascade = CascadeType.ALL, mappedBy = "topic")
private List<Post> posts = new ArrayList<>();

问题是,Hibernate 有一个错误,它不支持 @OrderedColumnmappedBy 在一起: JPA 2.0 @OrderColumn annotation in Hibernate 3.5

作为解决方案,我在实体 Post:

中手动更新订单列
@Column(name = "order_column")
private Integer orderColumn;

@PrePersist
@PreUpdate
private void updateOrderColumn() {
    // for changing order
    orderColumn = topic.getPosts().indexOf(this);
    // for persist
    if (orderColumn == -1)
        orderColumn = topic.getPosts().size();
}