3

I am building a chat application with Spring, Hibernate and JPA and I want two tables - chats and messages. Chat will have many messages, also id and user_first and user_second. Right now I am doing it with a composite primary key where the composite is user_first and user_second and the id is unique auto-increment:

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;
...

is there any better way to do it and why?

Update: Chat is a uniqe row between two people there cant be two chats with the same two users. I want to take all messages that I need along with the two users that had those messages, so I can put the sender id into a hashmap key and the messages into a value. To an answer bellow SessionId is a different thing than what my table chat is doing not a different way to implement what I want.

  • Why have the id fields if that's not your actual id (primary key)? I'd either drop the id field, or make it your @Id and add a unique constraint on the combination of the other two fields. – Dumidu Udayanga Feb 16 '19 at 14:12

1 Answers1

0

No it is not the best. The main role of a primary key is to bring uniqueness, secondary would be a fast access. Keys are used for caching as well, so the size of your key would detirmine how much you can cache as well. Making composite ckey would mean you need to override hashcode and equals possibly. You are overcomplicating it.

Obviously firstUsier Id and second user Id is not enough to bring uniqueness to your chat , because you can have many chats sessions between same users.

I think you should rename your id to "sessionID" use it as primary key and make the two relationships between yourtwo users outside of the primary key.

@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;
...

UPDATE: The question turned into Pros and Cons of Composite keys which has been discussed in details here Why are composite keys discouraged in hibernate?

Alexander Petrov
  • 9,204
  • 31
  • 70
  • No the chat means that it is a unique chat between 2 people with many messages there can't be 2 chats with the same people –  Feb 16 '19 at 12:22
  • I don't know what you are buildin, is it a student project is it a real world case. The expectation from a real world case that you will have chat uniqueness based on users is not serious. Even if you do that today I strongly advice you to bring sessionId even if you don't use it today activly tomorrow you may thank me :) Just modify the relationships to OnToOne if you insist on OneToOne – Alexander Petrov Feb 16 '19 at 12:25
  • why do I need a session Id? can't I use date and when the person opens the chat it gets a set amount of messages then when the user scrolls further it takes more of them so there isn't overloading of messages. –  Feb 16 '19 at 12:28
  • and this is the meaning of composite key? 2 people will always have a unique chat. –  Feb 16 '19 at 12:29
  • You can use a date as well. I personaly prefer numeric keys as they are more efficient. You can use guid as well., or you can use a date as long as your precision is good enough :) – Alexander Petrov Feb 16 '19 at 12:29
  • read this https://stackoverflow.com/questions/14112839/why-are-composite-keys-discouraged-in-hibernate the explanation here is very clear. – Alexander Petrov Feb 16 '19 at 12:30
  • but most of those I really overcome with the unique id that I put in every pair of users has a unique id. So I can reference the table with the id but at creation I am creating it with the composite key. –  Feb 16 '19 at 12:33
  • also I can create a foreign key from another table with the same id not using 2 columns –  Feb 16 '19 at 12:34
  • The thing is I wanted a better solution I want a chat table so I can have easier use with my hashtable, but you gave me a sessionid which doesn't have any connection with a chat. Chat and sessionid are two different things. And also about your update I never wanted to turn this into a discussion but what I saw from your link I really overcome with the id that I put. –  Feb 16 '19 at 12:38
  • "Better solution" I hope you get it ;) I think you are mixing up two concepts, your internal model and representation and your database model. Nothing is stopping you to present your internal model in whatever more convinient way you want. If you want to build composite based on the ids of the two users that is fine. But building in such specific way your DB representation is wel.... not very beautiful. Again I cant stop you in your search for fitting answer. I doubt you will find it here though. – Alexander Petrov Feb 16 '19 at 12:47