【问题标题】:Hibernate self referencing ManyToMany join into single list with annotationsHibernate 自引用 ManyToMany 加入带有注释的单个列表
【发布时间】:2020-12-02 15:09:53
【问题描述】:

我遇到了一个类似于 Tinder 匹配逻辑的问题,所以我以它为例。

我的用户可以通过具有两个用户引用的公共匹配实体在彼此之间进行“匹配”。

@Data
@Entity
@Table(name = "match")
@EqualsAndHashCode(callSuper = true)
public class Match extends PanacheEntity {

    @Column(name = "matchDate")
    Calendar matchDate;

    @ManyToOne
    @JsonIgnore
    User userA;

    @ManyToOne
    @JsonIgnore
    User userB;

  }
}

我喜欢对用户属于两个用户实体对象的所有匹配项进行单一引用,但是我需要选择(假设使用“mappedBy”)关系的另一端,是第一个或第二个用户。

@Data
@Entity
@Table(name = "user_")
@EqualsAndHashCode(callSuper = true)
public class User extends PanacheEntity {

    @Column(name = "email")
    String email;

    @Column(name = "name")
    String name;

    // Needs to contain all "Matches", no matter if the user is referenced as "A" or "B"
    @OneToMany
    List<Match> matches;
}

我希望列表匹配项填充以下查询表示的对象,即与用户相关的所有匹配项,独立于列。

select distinct match.id, user_a_id, user_b_id
from match,
     user_
where user_.id = match.user_a_id
   or user_.id = match.user_b_id

无论我是邀请者还是被邀请者,都可以为我作为用户提供与我相关联的任何连接对象。

有没有办法使用 Hibernate 注释来实现它?

【问题讨论】:

    标签: hibernate jpa join annotations mappedby


    【解决方案1】:

    可以使用@JoinColumn指定列名

    连接

    @Data
    @Entity
    @Table(name = "connection")
    @EqualsAndHashCode(callSuper = true)
    public class Connection extends PanacheEntity {
    
        @ManyToOne
        @JsonIgnore
        @JoinColumn(name = "inviter_id")
        User inviter;
    
        @ManyToOne
        @JsonIgnore
        @JoinColumn(name = "invited_id")
        User invited;
    }
    

    用户

    @Data
    @Entity
    @Table(name = "user_")
    @EqualsAndHashCode(callSuper = true)
    public class User extends PanacheEntity {
    
        @Column(name = "email")
        String email;
    
        @Column(name = "name")
        String name;
    
        @OneToMany(mappedBy = "inviter")
        List<Connection> inviterConnections;
     
        @OneToMany(mappedBy = "invited")
        List<Connection> invitedConnections;
    }
    

    基于 cmets 的更新

    你可以在Connection 上尝试@JoinColumns,如下所示,但它会给你和子句。

    @JoinColumns(value = {
                @JoinColumn(name = "id", referencedColumnName = "inviter_id"),
                @JoinColumn(name = "id", referencedColumnName = "invited_id") })
    User user;
    

    【讨论】:

    • 遗憾的是它没有按预期工作。它仍然需要另一侧的“mappedBy”属性指向两个用户变量之一,否则结果为空。您知道如何将其映射到两者吗?
    • 我已经添加了映射和更新的答案,请测试相同。
    • 但是现在我们有两个我想要阻止的用户的列表,我想要一个包含所有常见连接的列表,而不区分受邀者和邀请者。另一个例子是 Tinder 比赛,我对比赛和双方都感兴趣,而不是谁邀请了谁。也许我应该从一开始就举这个例子来说明清楚,sry
    • 您不需要添加映射依据。您可以使用连接存储库从连接表中获取数据。如果您分享您的服务类代码,那将很有帮助。
    • @SKK 我还没有服务类,我只是想让hibernate通过调用User.findById()找到引用的连接对象。我的意图不是在服务中进行额外的工作,而是尽可能将其完全覆盖在休眠注释上。我认为否则我也可以只使用我在问题中发布的 SQL 查询 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-03-17
    • 2013-03-08
    • 1970-01-01
    • 2015-12-17
    • 2012-09-08
    • 1970-01-01
    • 2014-08-31
    相关资源
    最近更新 更多