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

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

当前回答

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

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

其他回答

还有一种可能会在休眠状态下导致此错误。您可以将对象A的未保存引用设置为附加的实体B,并希望持久化对象C。即使在这种情况下,您也会遇到上述错误。

或者,如果你想使用最小的“权力”(例如,如果你不想级联删除)来实现你想要的,使用

import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;

...

@Cascade({CascadeType.SAVE_UPDATE})
private Set<Child> children;

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

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

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

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

当您具有OneToMany关系并且尝试将子实体添加到父实体中的列表中,然后通过父实体检索此列表(在保存此父实体之前),而不保存子实体本身时,也可能发生这种情况,例如:

Child childEntity = new Child();
parentEntity.addChild(childEntity);
parentEntity.getChildren(); // I needed the retrieval for logging, but one may need it for other reasons.
parentRepository.save(parentEntity);

保存父实体时引发了错误。如果我删除了前一行中的检索,则不会抛出错误,但当然这不是解决方案。

解决方案是保存子实体并将保存的子实体添加到父实体,如下所示:

Child childEntity = new Child();
Child savedChildEntity = childRepository.save(childEntity);
parentEntity.addChild(savedChildEntity);
parentEntity.getChildren();
parentRepository.save(parentEntity);

不要使用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);

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