具有连接表的单个实体上多对多

时间:2018-12-24 19:24:09

标签: java oracle hibernate

我有一项任务,要求某些“特殊”用户无需登录即可在帐户之间切换。首先,我有一个仅由用户ID组成的联接表。以PRIMARY_USER_ID和SECONDARY_USER_ID的形式作为来自USERS表的外键。首先需要实现的是用户之间所有连接的GET。 [{“ primary_username”,“ primary_email”,“ secondary_username”,“ secondary_email”}]。

我在User实体上创建了多对多关系,关系的两边都在User上。

@EqualsAndHashCode.Exclude
@ToString.Exclude
@ManyToMany(fetch = FetchType.LAZY, cascade = {
        CascadeType.PERSIST,
        CascadeType.MERGE
})
@JoinTable(name = "CONTACTS_ONE_LOGIN",
        joinColumns = { @JoinColumn(name = "PRIMARY_CONTACT")},
        inverseJoinColumns = {@JoinColumn(name = "SECONDARY_CONTACT")}
)
private Set<Contact> secondaryContacts = new HashSet<>();

@EqualsAndHashCode.Exclude
@ToString.Exclude
@ManyToMany(cascade = {
        CascadeType.REMOVE
},
        mappedBy = "secondaryContacts")
private Set<Contact> primaryContacts = new HashSet<>();

现在的问题是,当我想获取联系人之间的所有连接时,我首先需要从联接表中获取所有信息,然后遍历每个PRIMARY_CONTACT_ID以获得其已连接的联系人。这将导致非常低的性能。

我想将其更改为具有CONNECTED_USERS实体,该实体将具有两个USER上的多对一关系,而不是两个USER ID。

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "PRIMARY_CONTACT_ID")
private Contact contact;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "SECONDARY_CONTACT_ID")
private Contact contact;

我的问题是,这是否会提高性能,因为在我的开发数据库中我没有很多用户可以对其进行正确的测试?还是有更好的方法做到这一点?

1 个答案:

答案 0 :(得分:0)

由于我们对您的应用程序,数据或业务规则一无所知,因此我们很难猜测您的模型的性能如何。从您的问题来看,似乎只有少数用户受到此要求的影响。因此,除非您的总用户人数成千上万,否则您不必担心。

无论哪种方式,您建议的单独相交表的性能优势都不太可能证明维护该表的开销是合理的。我建议您建立一个基于复合函数的索引,如下所示(注意:现在我无法访问数据库,因此以下内容未经测试,可能包含语法错误):

create index connected_users_fbi on your_table (
    case when secondary_contact_id is not null then primary_contact_id end,
     secondary_contact_id);

此索引将有助于识别主要联系人和次要联系人。它还可能支持通过“索引跳过扫描”查找与次要联系人(如果需要该功能)连接的所有主要联系人。

显然,我不相信它,而是尝试使用实际数据量对其进行基准测试。您的项目应该有一个可以进行此类测试的性能环境。如果不是这样,那就注定了。