merge – Spring-Data JPA:保存引用现有实体的新实体

问题基本上与以下一样:

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

我正在创建一个引用现有的,独立的实体的新实体。现在当我将这个实体保存在我的spring数据库中时,抛出异常:

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

如果我们看到spring数据JPA的源代码中的save()方法,我们看到:

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

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

如果我们在AbstractEntityInformation中查看isNew()

public boolean isNew(T entity) {

    return getId(entity) == null;
}

所以基本上如果我保存()一个新的实体(id == null),弹簧数据将永远调用持久性,因此这种情况总是会失败。

当将新项目添加到集合中时,这似乎是一个非常典型的用例。

我该如何解决?

编辑1:

注意:

这个问题与How to save a new entity that refers existing entity in Spring JPA?没有直接关系。要详细说明,假设您通过http创建新实体的请求。然后,从请求中提取信息,并创建您的实体和现有的引用的实体。所以他们永远是分开的。

我想出的最好的是

public final T save(T containable) {
    // if entity containable.getCompound already exists, it
    // must first be reattached to the entity manager or else
    // an exception will occur (issue in Spring Data JPA ->
    // save() method internal calls persists instead of merge)
    if (containable.getId() == null
            && containable.getCompound().getId() != null){
        Compound compound = getCompoundService()
                .getById(containable.getCompound().getId());
        containable.setCompound(compound);   
    }
    containable = getRepository().save(containable);
    return containable; 
}

我们检查我们是否处于有问题的情况,如果是,只需通过其ID从数据库重新加载现有实体,并将新实体的字段设置为新加载的实例。然后会被附上。

这要求新实体的服务持有对引用实体的服务的引用。这不应该是一个问题,因为您正在使用弹簧,以便服务只能作为一个新的@Autowired字段添加。

另一个问题(在我的情况下,这个行为是实际需要的),您不能同时更改引用的现有实体,同时保存新的实体。所有这些更改都将被忽略。

重要的提示:

在很多可能的情况下,这可以简单得多。您可以向您的服务添加实体管理器的引用:

@PersistenceContext
private EntityManager entityManager;

并在上面的if(){}块使用

containable = entityManager.merge(containable);

而不是我的代码(未测试,如果它的工作原理)。

在我的例子中,类是抽象的,而@ManyToOne中的targetEntity也是抽象的。直接调用entityManager.merge(可包含)导致异常。但是,如果你的班级是具体的,这应该是有效的。

http://stackoverflow.com/questions/16559407/spring-data-jpa-save-new-entity-referencing-existing-one

本站文章除注明转载外,均为本站原创或编译
转载请明显位置注明出处:merge – Spring-Data JPA:保存引用现有实体的新实体