Q:

Composite ID in join-table

I have the following PostLike class:
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class PostLike extends BaseEntity {

    @ManyToOne
    @JoinColumn(name = "user_id")
    private User user;

    @ManyToOne
    @JoinColumn(name = "post_id")
    private Post post;
}

The class already has an ID field provided by parent BaseEntity class.
In the User class, I have the following field:
@OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
Set<PostLike> userLikes = new HashSet<PostLike>();

And in the Post class:
@OneToMany(mappedBy = "post")
private Set<PostLike> postLikes = new HashSet<PostLike>();

I want a PostLike to have a composite primary key, which consists of user_id and post_id.
Thanks in advance.

A:

As one way to do this you can use @EmbeddedId annotation and express this composite key with embeddable class:
@Entity
public class PostLike {

    @Embeddable
    private static class Id implements Serializable {

        @Column(name = "user_id")
        private Long userId;

        @Column(name = "post_id") 
        private Long postId;

        public Id() {
        }

        public Id(Long userId, Long postId) {
            this.userId = userId;
            this.postId = postId;
        }

        // equals and hashCode
    }

    @EmbeddedId
    Id id = new Id();

    @ManyToOne
    @JoinColumn(name = "user_id")
    private User user;

    @ManyToOne
    @JoinColumn(name = "post_id")
    private Post post;

    public PostLike() {
    }

    public PostLike(User user , Post post) {
        this.user = user;
        this.post = post;

        this.id.postId = post.getId();
        this.id.userId = user.getId();

        post.getUserLikes().add(this);
        user.getUserLikes().add(this);
    }
        ... // getters and setters
}

Some notes:
from javadoc of @EmbeddedId

There must be only one EmbeddedId annotation and
   no Id annotation when the EmbeddedId annotation is used.

from Java Persistence with Hibernate

The primary advantage of this strategy is the possibility for bidirectional navigation.
  ...
   A disadvantage is the more complex code needed to manage the
  intermediate entity instances to create and remove links, which you have to save
  and delete independently.

