0

I have Customer who has phones:

public class Customer {

    ...

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    @JoinColumn(name = "customer_id", nullable = false)
    private List<Phone> phones = new ArrayList<>();

}


public class Phone {

    ...

    @Column(name = "customer_id", insertable = false, updatable = false)
    private Long customer_id;

}

If I try to do em.merge(customer); then JPA will always insert all mapped columns (if Phone or Phones has new id, then they will be inserted) and will only update the columns that have changed (if Phone with existing id changes, then it will be updated).

but if I try to merge customer where phones are empty list then nothing happens. The question here is how to merge customer phones the way they are posted. For example if phones list is empty then it will be empty.


Initial state:

{
    "id" : "1",
    "phones" : []
}

Now posting that:

{
"id" : "1",
"phones" : [
        {
            "id" : "12",
            "type" : "mobile",
            "value" : "123"
        }
    ]
}

Will add new phone if phone with such id didn't exist. If there had been phone with id 12 then it would be updated. So in our case the phone with id 12 didn't exist, then after the post result is is the same:

{
"id" : "1",
"phones" : [
        {
            "id" : "12",
            "type" : "mobile",
            "value" : "123"
        }
    ]
}

But now if I post that:

{
    "id" : "1",
    "phones" : []
}

Then the result is still the same:

{
"id" : "1",
"phones" : [
        {
            "id" : "12",
            "type" : "mobile",
            "value" : "123"
        }
    ]
}

But I thought it would be the way i inserted it and the result would that:

{
    "id" : "1",
    "phones" : []
}

Why don't em.merge(customer) do it???

save function is here:

@Transactional
    public void save(Customer customer) {
        if (customer.getId() == null) {
            em.persist(customer);
        } else {
            em.merge(customer);
        }
    }

Some hackish solutions?

  • I could do something like em.remove(customer) and then em.persist(customer). That would work, but i know this can be achieved by em.merge(customer).
  • Or I could find specific customer phones, then delete them, and finally do the merge. That works as well. But still I believe that em.merge() is somehow capable of doing that by itself.
Kert Kukk
  • 666
  • 1
  • 10
  • 20
  • I don't understand the question but I'll just comment on the relation. Usually you would use `mappedBy` instead of a `joinColumn` in a `OneToMany` relationship. dunno if that gets you where you want to though.. – Jack Flamp Mar 16 '17 at 21:32
  • I am using unidirectional OneToMany relationship. So mappedBy is not helping here :) [link](http://stackoverflow.com/a/12041879/378151) – Kert Kukk Mar 16 '17 at 21:44
  • Ok nevermind then – Jack Flamp Mar 17 '17 at 05:30
  • Define what you mean by "insert all mapped columns and will only update the columns that have changed". Demonstrate that with a class and the SQL issued and what you think is a problem – Neil Stockton Mar 17 '17 at 06:39
  • 1
    You mean that "phones" field was DETACHED with values in it and when you merge (as empty) it is not updated? That would be specific to your JPA provider because the ones that use bytecode enhancement would detect the field has been changed. So tag your question against a particular JPA provider – Neil Stockton Mar 17 '17 at 11:21
  • Yes and I'm using Hibernate. (also added the Hibernate tag). @Neil Stockton – Kert Kukk Mar 17 '17 at 12:12

0 Answers0