-1

Having this entities:

User.java:

@Entity
@NoArgsConstructor
@Getter
@Setter
public class User {
    @Id
    private int id;
    private String username;
    @OneToMany(mappedBy = "owner")
    @MapKey(name = "friend_id")
    private Map<User, Friendship> friends = new HashMap<>();
}

Friendship:

@Entity
@Data
//@IdClass(Friendship.class)
public class Friendship implements Serializable {
    @Id
    private int owner_id;
    @Id
    private int friend_id;
    private String level;
    @ManyToOne
    @MapsId("owner_id")
    private User owner;
    @ManyToOne
    @MapsId("friend_id")
    private User friend;
}

I though I must have @IdClass or @EmbeddedId if I want to use two or more primary keys. But as shown above, I could ommit either, and just declare two primary keys (this is what I mean it "compiles"). So the question is, why to even bother using either of those annotations and just declare more keys?

generated table:

+-----------+--------------+------+-----+---------+-------+
| Field     | Type         | Null | Key | Default | Extra |
+-----------+--------------+------+-----+---------+-------+
| owner_id  | int          | NO   | PRI | NULL    |       |
| friend_id | int          | NO   | PRI | NULL    |       |
| level     | varchar(255) | YES  |     | NULL    |       |
+-----------+--------------+------+-----+---------+-------+
milanHrabos
  • 2,010
  • 3
  • 11
  • 45
  • What do "compiles" & "having more then one primary key" mean? What has your research shown towards answering why there is a PK & what a PK or alternate key is & "the benefit of explicitly declaring it with @IdClass"? [ask] – philipxy Sep 10 '21 at 11:50
  • @philipxy I though I *must have* `@IdClass` or `@EmbeddedId` if I want to use *two* or more primary keys. But as shown above, I *could* ommit either, and just declare two primary keys (this is what I mean it "compiles"). So the question is, why to even bother using either of those annotations and just declare more keys? – milanHrabos Sep 10 '21 at 11:54
  • Please clarify via edits, not comments. PS There can only be one PK. There can be multiple "candidate"/unique keys--ond of which one can be PK. But neither of the 2 columns that would make up a composite PK would be themselves candidates for PKs. Neither uniquely determines an entity. Read about keys. Please research before considering posting a question. – philipxy Sep 10 '21 at 11:56
  • The definition of the table that was generated by this entity, *had* 2 primary keys (`owner_id` and `friend_id`). So I don't understand your statement, *There can only be one PK. – milanHrabos Sep 10 '21 at 11:59
  • That table does not have 2 PKs. It has 2 FKs, columns whose values are PKs elsewhere. – philipxy Sep 10 '21 at 12:00
  • @philipxy well I still see *two* `PRI` in column of `Key` in the table above – milanHrabos Sep 10 '21 at 12:01

1 Answers1

0

As it's mentioned in the hibernate documentation:

The restriction that a composite identifier has to be represented by a "primary key class" (e.g. @EmbeddedId or @IdClass) is only JPA-specific.

Hibernate does allow composite identifiers to be defined without a "primary key class" via multiple @Id attributes.

Although the mapping is much simpler than using an @EmbeddedId or an @IdClass, there’s no separation between the entity instance and the actual identifier. To query this entity, an instance of the entity itself must be supplied to the persistence context.

@Entity
public class Friendship implements Serializable {

    /*
        It's better to use object wrapper classes instead of the corresponding 
        primitive types. Because, for example, uninitialized Integer is null,
        but uninitialized int is 0 that can be a legal id.
    */
    @Id
    private Integer ownerId;

    @Id
    private Integer friendId;

    public Friendship() {

    }

    public Friendship(Integer ownerId, Integer friendId) {
        this.ownerId = ownerId;
        this.friendId = friendId;
    }
    // ...
}

Friendship friendship = entityManager.find(Friendship.class, new Friendship(ownerId, friendId));
SternK
  • 11,649
  • 22
  • 32
  • 46