使用Hibernate保存对象时收到以下错误
object references an unsaved transient instance - save the transient instance before flushing
使用Hibernate保存对象时收到以下错误
object references an unsaved transient instance - save the transient instance before flushing
当前回答
我相信这可能只是重复答案,但为了澄清,我在@OneToOne映射和@OneToMany上得到了这个答案。在这两种情况下,我添加到Parent的Child对象尚未保存在数据库中。因此,当我将Child添加到Parent,然后保存Parent时,Hibernate会在保存Parent之前抛出“对象引用未保存的瞬态实例-在刷新之前保存瞬态实例”消息。
在父级对子级的引用上添加cascade={CascadeType.ALL}解决了这两种情况下的问题。这保存了子对象和父对象。
很抱歉有重复的回答,只是想进一步澄清一下。
@OneToOne(cascade = {CascadeType.ALL})
@JoinColumn(name = "performancelog_id")
public PerformanceLog getPerformanceLog() {
return performanceLog;
}
其他回答
不要使用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);
而如果对象只是一个“新”对象,那么它将抛出相同的错误。
除了所有其他好的答案之外,如果您使用merge来持久化一个对象,并且意外地忘记在父类中使用该对象的合并引用,那么可能会发生这种情况。考虑以下示例
merge(A);
B.setA(A);
persist(B);
在这种情况下,您合并了A,但忘记了使用A的合并对象。为了解决这个问题,您必须像这样重写代码。
A=merge(A);//difference is here
B.setA(A);
persist(B);
或者,如果你想使用最小的“权力”(例如,如果你不想级联删除)来实现你想要的,使用
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
...
@Cascade({CascadeType.SAVE_UPDATE})
private Set<Child> children;
您应该在集合映射中包含cascade=“all”(如果使用xml)或cascade=CascadeType.all(如果使用注释)。
发生这种情况是因为实体中有一个集合,而该集合中有一项或多项不在数据库中。通过指定上述选项,您可以告诉hibernate在保存父对象时将其保存到数据库中。
在我的例子中,使用Cascade.ALL是在表中添加不必要的条目,表中已经有了相同的对象(生成没有id的子值就可以做到这一点)。所以我必须先从存储库中获取子对象,并将其设置为主对象,而不是导致问题的对象。
Student s = studentRepo.findByName(generatedObject.getStudent().getName())
generatedObject.student(s);