例外JPA/Hibernate:拯救儿童@manytoone关系的脱离实体通过



无法保存子对象参考。

员工父对象包含儿童雇员_detail,该对象还定义了一个@manytoone来保存地址对象。

表结构

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控制器方法中:

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

我无法使用儿童桌子imhoseedetail保存地址详细信息。这里怎么了?

应用cascadeType.merge也适用于下面的地址实体

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

并使用merge()而不是持久保存更改

编辑

是的,您也必须应用cascadeType。

有几个方案您需要考虑。

如下所述。

当您在根实体上调用persist()时,所有实体关联与cascadeType映射的所有实体关联也将传递给persist()(传递螺旋)。现在,如果您的对象图中的任何实体被分离为persist()也将被要求为该实体,您将获得该实体的例外。

为了保存包括独立和瞬态实例在内的对象的完整图,请标记您与cascadeType.merge的关联。与cascadeType.merge映射的关联。合并的行为是,它将在持久性上下文中合并任何被传递给现有实体的独立实体,或者如果实体是瞬态的,则它将使其持久。

因此,在尝试保存您的实体图时,您需要根据信息选择是使用Persist()还是Merge()或Merge()您还必须考虑每个关联上设置的级联类型。

对于您的代码。.我看到您在opplyeedetail实例上设置的地址实例是从另一个已经获取的Emplyeedetail实例获得的时。

您可以在下面的链接上获取更多详细信息

JPA EntityManager:为什么在Merge()?

上使用Persist()?

如果您不想使用独立实例,则可以通过进行对话来扩展持久性上下文。

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

最新更新