Johannes Rummel
Johannes Rummel

Reputation: 3

JPA, persist Entity with OneToMany where some of the Many already exist

I have the situation where I have a class A having a OneToMany relationship to class B. Class B only consists of a few attributes like id, firstName and lastName. The id is generated through UUID. Since it is very likely that very much instances of A will reference an instance of B with the same values for firstName and lastName plus those values in instances of B are very unlikely to ever change. So I decided to avoid duplicates and let reference instances of A to the same instances (in the database) of B if the other parameters are the same.

Example:

b: "John Doe"
a: a1 ("Foo Bar", "John Doe"), a2 ("John Doe", "Alan Smith").

To achieve this I always check the database for an already existing record with the very same parameters if a new B is added to A. If so, I'll just overwrite the id of that instance of B with the one from the database and add it to A afterwards.

Now here comes my problem. Everything is working fine but if I persist an A where I manually changed the Id of an B so that it has the same Id as a B already existing in the database I'll get an Exception:

Caused by: org.hibernate.exception.ConstraintViolationException:
Duplicate entry '2cfa1412-5f64-4a9c-b55c-f7db1148bef9' for key 'PRIMARY'

So my questions are:

Best regards

Upvotes: 0

Views: 796

Answers (1)

JB Nizet
JB Nizet

Reputation: 691735

First of all, you don't have a OneToMany, but a ManyToMany.

Now, to fix your problem, don't assign the ID of the attached B to your detachedB, but replace the detached B by the attached one:

Set<B> bs = new HashSet<B>(a.getBs()); // copy the list of Bs
a.getBs().clear();
for (B b : bs) {
    B existingB = searchBWithSameValuesAs(b);
    if (existingB != null) {
        a.getBs().add(existingB);
    }
    else {
        em.persist(b);
        a.getBs().add(b);
    }
}

Upvotes: 1

Related Questions