Hibernate: Unique constraint for list of Embeddables (@ElementCollection)

Given an Enitiy Product

@Entity
public class Product {

    private Long id;
    private List<Review> reviews;

    public Product() {}

    @Id
    @GeneratedValue
    public Long getId() {
        return this.id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    @ElementCollection
    public List<Review> getReviews() {
        return reviews;
    }

    public void setReviews(List<Review> reviews) {
        this.reviews = reviews;
    }

    // equals() and hashCode() omitted for brevity
}

And an Embeddable Review

@Embeddable
public class Review {

    private Customer author;
    private String title;
    private String comment;

    public Review() {}

    @ManyToOne(optional = false)
    @Column(unique = true)
    public Customer getAuthor() {
        return author;
    }

    public void setAuthor(Customer author) {
        this.author = author;
    }

    @Column(nullable = false)
    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    @Column(nullable = false, length = 2000)
    public String getComment() {
        return comment;
    }

    public void setComment(String comment) {
        this.comment = comment;
    }
}

How can I set an unique constraint for the Review‘s author. In other words: I want to make sure, that for a given product each review has a different author.

Can I use @NaturalId? Do I use @Column(unique = true)? I already found a similar question on StackOverflow, but in my case it’s a list of Embeddables and not just a member, so that that approach won’t work, I guess.

Thanks a lot in advance!

Answer

If you are talking about having a unique database index added during schema generation then you can do this as below:

@ElementCollection
@CollectionTable(name = "product_reviews", 
       uniqueConstraints = {@UniqueConstraint(columnNames={"product_id", "author_id"})})
public List<Review> getReviews() {
    return reviews;
}

Leave a Reply

Your email address will not be published. Required fields are marked *