使用Hibernate保存对象时收到以下错误

object references an unsaved transient instance - save the transient instance before flushing

当前回答

您应该在集合映射中包含cascade=“all”(如果使用xml)或cascade=CascadeType.all(如果使用注释)。

发生这种情况是因为实体中有一个集合,而该集合中有一项或多项不在数据库中。通过指定上述选项,您可以告诉hibernate在保存父对象时将其保存到数据库中。

其他回答

当Hibernate认为需要保存与正在保存的对象关联的对象时,在保存对象时会发生这种情况。

我遇到了这个问题,不想保存对引用对象的更改,所以我希望级联类型为NONE。

诀窍是确保设置了被引用对象中的ID和VERSION,这样Hibernate就不会认为被引用对象是需要保存的新对象。这对我有用。

查看要保存的类中的所有关系,以计算关联对象(以及关联对象的关联对象),并确保在对象树的所有对象中设置了ID和VERSION。

不要使用Cascade.All,除非你真的需要。角色和权限具有双向manyToMany关系。那么下面的代码就可以正常工作了

    Permission p = new Permission();
    p.setName("help");
    Permission p2 = new Permission();
    p2.setName("self_info");
    p = (Permission)crudRepository.save(p); // returned p has id filled in.
    p2 = (Permission)crudRepository.save(p2); // so does p2.
    Role role = new Role();
    role.setAvailable(true);
    role.setDescription("a test role");
    role.setRole("admin");
    List<Permission> pList = new ArrayList<Permission>();
    pList.add(p);
    pList.add(p2);
    role.setPermissions(pList);
    crudRepository.save(role);

而如果对象只是一个“新”对象,那么它将抛出相同的错误。

错误的一个可能原因是父实体的值设置不存在;例如,对于部门员工关系,为了修复错误,您必须编写以下内容:

Department dept = (Department)session.load(Department.class, dept_code); // dept_code is from the jsp form which you get in the controller with @RequestParam String department
employee.setDepartment(dept);

在我的例子中,当我试图使用对具有空id的实体的引用来检索相关实体时,发生了这种情况。

@Entity
public class User {
@Id
private Long id;
}

@Entity
public class Address {
@Id
private Long id;
@JoinColumn(name="user_id")
@OneToOne
private User user;
}

interface AddressRepository extends JpaRepository<Address, Long> {
Address findByUser(User user);
}

User user = new User(); // this is transient, does not have id populated
// user.setId(1L) // works fine if this is uncommented

addressRepository.findByUser(user); // throws exception

除了所有其他好的答案之外,如果您使用merge来持久化一个对象,并且意外地忘记在父类中使用该对象的合并引用,那么可能会发生这种情况。考虑以下示例

merge(A);
B.setA(A);
persist(B);

在这种情况下,您合并了A,但忘记了使用A的合并对象。为了解决这个问题,您必须像这样重写代码。

A=merge(A);//difference is here
B.setA(A);
persist(B);