异常 JPA/Hibernate:分离的实体在保存子 @ManyToOne 关系时传递给持久化 [英] Exception JPA/Hibernate: detached entity passed to persist while saving child @ManyToOne relation

查看:37
本文介绍了异常 JPA/Hibernate:分离的实体在保存子 @ManyToOne 关系时传递给持久化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

无法保存子对象引用.

Employee 父对象包含子employee_detail,它也定义了一个@ManyToOne 来保存Address 对象.

Employee parent object contains the child employee_detail which also has a @ManyToOne defined to save Address object.

表格结构

EMPLOYEE
ID   BIGINT(20) NOT NULL AUTO_INCREMENT
NAME VARCHAR(100) NOT NULL

EMPLOYEE_DETAIL
ID              BIGINT(20) NOT NULL AUTO_INCREMENT
EMPLOYEE_ID     BIGINT(20) NOT NULL
ADDRESS_ID      BIGINT(20) NOT NULL

实体

@Entity
@Table(name = "employee")
public class Employee {
 @Id
 @GeneratedValue(strategy = GenerationType.AUTO)
 @Column(name = "id")
 private Long id;

 @Column(name = "name")
 private String name;

 @OneToMany(mappedBy = "employee", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
 private List < EmployeeDetail > employeeDetails = new ArrayList < > ();

 public void addEmployeeDetail(EmployeeDetail ed) {
  employeeDetails.add(ed);
  ed.setEmployee(this);
 }

}

@Entity
@Table(name = "employee_detail")
public class EmployeeDetail {
 @Id
 @GeneratedValue(strategy = GenerationType.AUTO)
 @Column(name = "id")
 private Long id;

 @ManyToOne(optional = false, cascade = CascadeType.PERSIST)
 @JoinColumn(name = "employee_id")
 private Employee employee;

 @ManyToOne(optional = false, cascade = CascadeType.PERSIST)
 @JoinColumn(name = "address_id")
 private Address address;
}

在 REST 控制器方法中:

In the REST Controller method:

public void saveEmployee(@RequestBody Employee employee)
{
    EmployeeDetail employeeDetail = new EmployeeDetail();
    employeeDetail.setEmployee(employee);

    for(EmployeeDetail ed : employee.getEmployeeDetails())
    {
        Address address = addressService.findOne(ed.getAddress().getId());
        employeeDetail.setAddress(address);
    }

    employee.addEmployeeDetail(employeeDetail);

    //SAVE
    employeeService.create(employee);
}

例外:

nested exception is org.hibernate.PersistentObjectException: detached entity passed to persist: com.abc.Address

我无法使用子表 EmployeeDetail 保存地址详细信息.这里有什么问题?

I am unable to save the Address details with the child table EmployeeDetail. What is wrong here?

推荐答案

对 Address 实体也应用 CascadeType.MERGE 如下

Apply CascadeType.MERGE too for Address entity as below

 @ManyToOne(optional = false, cascade = {CascadeType.PERSIST,CascadeType.MERGE})
 @JoinColumn(name = "address_id")
 private Address address;

并使用merge() 而不是persist 来保存您的更改

and use merge() instead of persist to save your changes

编辑

是的,您也必须为 EmployeeDetail 应用 CascadeType.MERGE ..否则,如果您在从 Employee 开始的对象网络中有一个分离的 EmployeeDetail 实例,您将得到相同的异常.

Yes you will have to apply the CascadeType.MERGE for EmployeeDetail too .. otherwise you will get the same exception if you have a detached EmployeeDetail instance in you network of objects starting from Employee.

您需要考虑几种情况.如下所述.

There are couple of scenarios which you will need to consider.As explained below.

当您在根实体上调用 persist() 时,所有与 CascadeType.PERSIST 映射的实体关联也会传递给 persist() (传递持久性).现在,如果对象图中的任何实体被分离,persist() 也会为该实体调用,并且您将获得该实体的异常.

When you call persist() on your root entity all the entity association mapped with CascadeType.PERSIST are also passed to the persist() (transitive peristence) . Now if any of your entity in the object graph is detached persist() will be called for that entity too and you will get an exception for that entity.

为了保存包括分离和瞬态实例的完整对象图,标记您与 CascadeType.MERGE 的关联并在您的根实体上调用 merge() .. 现在 merge() 操作将级联到所有实体与 CascadeType.MERGE 映射的关联.合并的行为是它将传递给它的任何分离的实体合并到持久性上下文中的现有实体,或者如果实体是瞬态的,它将使其持久化.

In order to save your complete graph of objects which includes both detached and transient instances , mark your association with CascadeType.MERGE and call merge() on your root entity .. Now merge() operation will be cascaded to all the entity association mapped with CascadeType.MERGE. The behaviour of merge is that it will merge any detached entity being passed to it to the existing entity in the persistence context or if the entity is transient it will make it persistent.

因此,在尝试保存实体图时,您需要根据您要保存的实体图是否只有瞬态实例或同时具有瞬态和分离实例的信息来选择是使用persist() 还是merge().您还必须考虑在每个关联上设置的级联类型.

So while trying to save you entity graph you need to choose whether to use persist() or merge() based on the info whether the entity graph you are going to save has only transient instances or it has both transient and detached instances.You will also have to consider the cascade type set on each association.

对于您的代码 .. 我看到您在 EmployeeDetail 实例上设置的 Address 实例已分离,因为您是从另一个已获取的 EmplyeeDetail 实例中获取它的.

For your code .. i see the Address instance you are setting on the EmployeeDetail instance is detached as you are getting it from another already fetched EmplyeeDetail instance.

您可以通过以下链接获得更多详细信息

You can get more detail on below link

JPA EntityManager:为什么要使用 persist() 而不是 merge()?

如果您不想使用分离的实例,您还可以通过创建对话来扩展您的持久性上下文.更多内容见下文

You can also extend your persistence context by creating conversations if you dont want to work with detached instances.More on this below

http://www.thoughts-on-java.org/unsychronized-persistencecontext-implement-conversations-jpa/

这篇关于异常 JPA/Hibernate:分离的实体在保存子 @ManyToOne 关系时传递给持久化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆