且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

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

更新时间:2022-11-04 22:33:33

我想出的***的是

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设置,并将新实体的字段设置为此新加载的实例。然后它将被附加。

We check if we are in the problematic situation and if yes just reload the existing entity from the database by its id and set the field of the new entity to this freshly loaded instance. It then will be attached.

这要求新实体的服务保存对引用实体的服务的引用。这应该不是问题,因为您仍然使用spring,因此可以将服务添加为新的 @Autowired 字段。

This requires that the service for new entity holds a reference to the service of the referenced entity. This should not be an issue since you are using spring anyway so that service can just be added as a new @Autowired field.

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

Another issue however (in my case this behavior is actually desired) that you can't change the referenced existing entity at the same time while saving the new one. All those changes will be ignored.

重要提示:

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

In many and probably your cases this can be much simpler. You can add a reference of entity manager to your service:

@PersistenceContext
private EntityManager entityManager;

以上 if(){} 阻止使用

containable = entityManager.merge(containable);

而不是我的代码(如果有效则未经测试)。

instead of my code (untested if it works).

在我的例子中,类是抽象的, @ManyToOne 中的 targetEntity 因此也是抽象的。直接调用entityManager.merge(可包含)然后会导致异常。但是,如果你的课程都具体,那么这应该有效。

In my case the classes are abstract and targetEntity in @ManyToOne is hence abstract too. Calling entityManager.merge(containable) directly then leads to an exception. However if your classes are all concrete this should work.