复合主键是最佳解决方案吗 - Hibernate Spring

3

我正在使用Spring、Hibernate和JPA构建一个聊天应用程序,我需要两个表 - chats 和 messages。Chat将有许多消息,还有id、user_first和user_second。目前我正在使用一个复合主键来完成这个任务,其中复合部分为user_first和user_second,id是唯一的自动递增:

public class ChatPK implements Serializable {
    protected int firstUser;

    protected int secondUser;
... 

@Entity
@IdClass(ChatPK.class)
@Table(name = "chats1")
public class Chat implements Serializable {
    @Id
    private int firstUser;

    @Id
    private int secondUser;

    @Column(name = "id", unique = true, nullable = false, insertable = false, updatable = false)
    @GeneratedValue(strategy= GenerationType.IDENTITY)
    private int id;
...

有没有更好的方法来做这件事,为什么?

更新:聊天是两个人之间的唯一行,不能有相同两个用户的两个聊天。我想获取所有需要的消息以及发送这些消息的两个用户,这样我就可以将发送者ID放入哈希映射键中,将消息放入值中。对于下面的答案,SessionId是与我的chat表不同的东西,而不是我想要实现的不同方式。


为什么有id字段,如果它不是实际的id(主键)?我要么删除id字段,要么将其作为@Id,并在其他两个字段的组合上添加唯一约束。 - Dumidu Udayanga
1个回答

0

不,这不是最好的方法。主键的主要作用是带来唯一性,其次是快速访问。键也用于缓存,因此您的键的大小将确定您可以缓存多少数据。创建组合键可能意味着您需要重写哈希码和相等方法。您正在过度复杂化问题。

显然,仅使用第一个用户ID和第二个用户ID无法为您的聊天带来唯一性,因为您可以在同一用户之间拥有多个聊天会话。

我认为您应该将自己的ID重命名为"sessionID",并将其用作主键,并在主键之外建立两个用户之间的两个关系。

@Entity
@Table(name = "chats1")
public class Chat implements Serializable {
    @ManyToOne
    private User firstUser;

    @ManyToOne
    private User secondUser;

    @Id
    @Column(name = "sessionId")
    @GeneratedValue(strategy= GenerationType.IDENTITY)
    private int sessionId;
...

更新:该问题已转变为复合键的优缺点,这个问题已经在为什么在Hibernate中不建议使用复合键?中详细讨论。


不,聊天指的是两个人之间的独特聊天,其中有许多消息。不能有两个与同一人的聊天。 - user6534435
我不知道你正在构建什么,是一个学生项目还是一个真实的案例。在真实世界的情况下,期望您将根据用户拥有聊天唯一性并不严重。即使您今天这样做,我强烈建议您带上sessionId,即使您今天没有积极使用它,明天您可能会感谢我 :) 如果您坚持要OneToOne,请将关系修改为OnToOne。 - Alexander Petrov
为什么需要会话ID?我不能使用日期吗?当用户打开聊天时,它会获取一定数量的消息,然后当用户滚动更多时,它会获取更多消息,这样就不会出现消息过载。 - user6534435
但是,我通过为每对用户设置唯一的ID来克服了大多数问题。因此,我可以使用该ID引用表,但在创建时,我将其创建为复合键。 - user6534435
我也可以从另一张表中使用相同的ID创建外键,而不使用2个列。 - user6534435
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,