Spring-Data JPA: save new entity referencing existing one

beginner_ picture beginner_ · May 15, 2013 · Viewed 43.9k times · Source

The question is basically the same as below one:

JPA cascade persist and references to detached entities throws PersistentObjectException. Why?

I'm creating a new entity that references an existing, detached one. Now when I save this entity in my spring data repository an exception is thrown:

org.springframework.dao.InvalidDataAccessApiUsageException: detached entity passed to persist

if we look at the save() method in source code of spring data JPA we see:

public <S extends T> S save(S entity) {

    if (entityInformation.isNew(entity)) {
        em.persist(entity);
        return entity;
    } else {
        return em.merge(entity);
    }
}

and if we look at isNew() in AbstractEntityInformation

public boolean isNew(T entity) {

    return getId(entity) == null;
}

So basically if i save() a new entity (id == null), spring data will always call persist and hence this scenario will always fail.

This seems to be a very typical use case when adding new items to collections.

How can I resolve this?

EDIT 1:

NOTE:

This issue is NOT directly related to How to save a new entity that refers existing entity in Spring JPA?. To elaborate assume you get the request to create the new entity over http. You then extract the information from the request and create your entity and the existing referenced one. Hence they will always be detached.

Answer

Jonas Geiregat picture Jonas Geiregat · Aug 6, 2014

I had a similar issue where I was trying to save an new entity object with an already saved entity object inside.

What I did was implemented Persistable< T > and implemented isNew() accordingly.

public class MyEntity implements Persistable<Long> {

    public boolean isNew() {
        return null == getId() &&
            subEntity.getId() == null;
    }

Or you could use AbstractPersistable and override the isNew there ofcourse.

I don't know if this will be considered a good way of handling this issue but it worked out quite good for me and besides feels very natural to do.