Hibernate - ManyToOne - 保存 - org.hibernate.TransientObjectException:

Kum*_*r D 1 hibernate jpa

当我尝试保存顶级实体(使用JPA)时,我是否需要从数据库中新获取ManyToOne映射实体并设置它或者我不能设置Id(manyToOne映射实体并保存顶级实体?当不新鲜时)它抛出的实体:org.hibernate.TransientObjectException:

我们正在使用的表结构:

DEPARTMENT(DEPARTMENT_ID BIGINT, NAME VARCHAR(128))

EMPLOYEE(EMPLOYEE_ID BIGINT, NAME VARCHAR(128), DEPARTMENT_ID BIGINT)

Entities:
class Department
{
   @Id
   Long departmentId;
   String name;
   @Version
   Long versionNumber;
}

class Employee
{
   @Id
   Long employeeId;
   String name;
   @ManyToOne
   Department department;
   @Version
   Long versionNumber
}
Run Code Online (Sandbox Code Playgroud)

(这两个类都有所有字段的setter和getter方法以及默认构造函数,构造函数将主键作为参数)现在如果我想用departmentId(比如100)保存Employee,我是否需要先获取Department记录然后设置它在员工?

我不能直接创建Department的实例(通过设置主键(departmentId))并在Employee中设置Department实例并保存Employee?当我这样做时,它抛出org.hibernate.TransientObjectException.

有关最佳实践的建议吗?

先感谢您

Chs*_*y76 7

如果要将Employee实例与新的 `Department实例相关联,可以设置适当的级联行为,让Hibernate处理整个事情:

class Employee {
  ...
  @ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
  Department department;
}
Run Code Online (Sandbox Code Playgroud)

请注意,你希望使用CascadeType.ALL,因为删除雇员不应该删除部门.

如果,OTOH,您想要将您的Employee实例与现有的 `Department实例相关联,那么您的最佳方法确实是加载它.您可以为此目的使用session.load()方法,该方法不会访问数据库.

另一种解决方案是使用session.merge(),Employee其上传播(如上所述的级联)Department.但这可能会产生副作用.