对象引用未保存的瞬态实例 – 在刷新之前保存瞬态实例
我使用Hibernate保存对象时收到以下错误
object references an unsaved transient instance - save the transient instance before flushing
您应该在集合映射中包含cascade="all"
(如果使用xml)或cascade=CascadeType.ALL
(如果使用注释)。
发生这种情况是因为您的实体中有一个集合,并且该集合中有一个或多个项目不在数据库中。 通过指定上述选项,您可以告诉hibernate在保存它们的父级时将它们保存到数据库中。
我相信这可能只是重复的答案,但只是为了澄清,我得到了@OneToOne
映射以及@OneToMany
。 在这两种情况下,事实上,我添加到Parent
的Child
对象并没有保存在数据库中。 所以当我将Child
添加到Parent
,然后保存了Parent
,当保存Parent
,Hibernate会抛弃"object references an unsaved transient instance - save the transient instance before flushing"
消息。
在Parent's
引用Child
cascade = {CascadeType.ALL}
添加cascade = {CascadeType.ALL}
解决了这两种情况下的问题。 这救了Child
和Parent
。
对不起,任何重复的答案,只是想进一步澄清为乡亲。
@OneToOne(cascade = {CascadeType.ALL}) @JoinColumn(name = "performancelog_id") public PerformanceLog getPerformanceLog() { return performanceLog; }
当Hibernate认为需要保存与保存的对象相关的对象时,保存对象时会发生这种情况。
我有这个问题,不想保存对引用对象的更改,所以我想级联types为NONE。
诀窍是确保引用对象中的ID和VERSION被设置,以便Hibernate不会认为引用的对象是需要保存的新对象。 这对我有效。
仔细检查保存的类中的所有关系,以确定关联对象(以及关联对象的关联对象),并确保在对象树的所有对象中都设置了ID和VERSION。
或者,如果你想使用最小的“权力”(例如,如果你不想级联删除)来实现你想要的,使用
import org.hibernate.annotations.Cascade; import org.hibernate.annotations.CascadeType; ... @Cascade({CascadeType.SAVE_UPDATE}) private Set<Child> children;
这发生在持久化数据库中的现有logging具有用@Version注释的字段的NULL值(用于乐观locking)的实体时。 在数据库中将NULL值更新为0已将其更正。
这不是错误的唯一原因。 我刚刚在编码中遇到了一个错字,我相信这个错误会设置一个已经保存的实体的值。
X x2 = new X(); x.setXid(memberid); // Error happened here - x was a previous global entity I created earlier Y.setX(x2);
我发现确切地find哪个variables导致错误(在这种情况下String xid
)的错误。 我在整个保存实体的代码块周围使用了一个接口,并打印了这些痕迹。
{ code block that performed the operation } catch (Exception e) { e.printStackTrace(); // put a break-point here and inspect the 'e' return ERROR; }
在我的情况下,这是由于在双向关系的@ManyToOne
方没有CascadeType
造成的。 更确切地说,我在@OneToMany
方面有CascadeType.ALL
,并没有@ManyToOne
。 将CascadeType.ALL
添加到@ManyToOne
解决了这个问题。 一对多的方面:
@OneToMany(cascade = CascadeType.ALL, mappedBy="globalConfig", orphanRemoval = true) private Set<GlobalConfigScope>gcScopeSet;
多对一方 (造成问题)
@ManyToOne @JoinColumn(name="global_config_id") private GlobalConfig globalConfig;
多对一 (通过添加CascadeType.PERSIST
修复)
@ManyToOne(cascade = CascadeType.PERSIST) @JoinColumn(name="global_config_id") private GlobalConfig globalConfig;
如果你的集合是可空的,只需尝试: object.SetYouColection(null);
为了增加我的2美分,当我不小心发送null
作为ID时,我得到了同样的问题。 下面的代码描述了我的场景(和OP没有提到任何特定的场景) 。
Employee emp = new Employee(); emp.setDept(new Dept(deptId)); // --> when deptId PKID is null, same error will be thrown // calls to other setters... em.persist(emp);
在这里,我将现有的部门ID设置为一个新的员工实例,而实际上并没有首先获取部门实体,因为我不想另外select查询来触发。
在某些情况下, deptId
PKID来自调用方法为null
,我得到相同的错误。
所以,注意PK ID的null
值
我得到这个错误,当我使用
getSession().save(object)
但使用时没有问题
getSession().saveOrUpdate(object)
除了所有其他的好的答案之外,如果你使用merge
来保存一个对象,并且不小心忘记在父类中使用对象的合并引用,就会发生这种情况。 考虑下面的例子
merge(A); B.setA(A); persist(B);
在这种情况下,您合并A
但忘记使用A
合并对象。 要解决这个问题,你必须像这样重写代码。
A=merge(A);//difference is here B.setA(A); persist(B);
另外一个可能的原因是:就我而言,我试图在拯救父母之前,把这个孩子拯救在一个全新的实体上。
这个代码在User.java模型中是这样的:
this.lastName = lastName; this.isAdmin = isAdmin; this.accountStatus = "Active"; this.setNewPassword(password); this.timeJoin = new Date(); create();
setNewPassword()方法创build一个PasswordHistorylogging,并将其添加到User中的历史logging集合中。 由于create()语句还没有被父执行,所以它试图保存到尚未创build的实体的集合中。 我所需要做的就是在调用create()之后移动setNewPassword()调用。
this.lastName = lastName; this.isAdmin = isAdmin; this.accountStatus = "Active"; this.timeJoin = new Date(); create(); this.setNewPassword(password);
解决这个问题的简单方法是保存这两个实体。 首先保存子实体,然后保存父实体。 因为父实体依赖于子实体的外键值。
简单的一对一关系考试
insert into Department (name, numOfemp, Depno) values (?, ?, ?) Hibernate: insert into Employee (SSN, dep_Depno, firstName, lastName, middleName, empno) values (?, ?, ?, ?, ?, ?) Session session=sf.openSession(); session.beginTransaction(); session.save(dep); session.save(emp);
还有另一种可能性,可能会导致在hibernate这个错误。 您可以将对象A
的未保存的引用设置为附加的实体B
并且希望保留对象C
即使在这种情况下,你也会得到上述的错误。
不要使用Cascade.All
直到你真的必须。 Role
和Permission
有双向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);
有这么多的可能性,这个错误还有一些其他的可能性也是添加页面或编辑页面。 在我的情况下,我试图挽救一个对象AdvanceSalary。 问题是,在编辑AdvanceSalary employee.employee_id为空因为在编辑我没有设置employee.employee_id。 我做了一个隐藏的领域,并设置它。 我的代码工作得很好。
@Entity(name = "ic_advance_salary") @Table(name = "ic_advance_salary") public class AdvanceSalary extends BaseDO{ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id") private Integer id; @ManyToOne(fetch = FetchType.EAGER) @JoinColumn(name = "employee_id", nullable = false) private Employee employee; @Column(name = "employee_id", insertable=false, updatable=false) @NotNull(message="Please enter employee Id") private Long employee_id; @Column(name = "advance_date") @DateTimeFormat(pattern = "dd-MMM-yyyy") @NotNull(message="Please enter advance date") private Date advance_date; @Column(name = "amount") @NotNull(message="Please enter Paid Amount") private Double amount; @Column(name = "cheque_date") @DateTimeFormat(pattern = "dd-MMM-yyyy") private Date cheque_date; @Column(name = "cheque_no") private String cheque_no; @Column(name = "remarks") private String remarks; public AdvanceSalary() { } public AdvanceSalary(Integer advance_salary_id) { this.id = advance_salary_id; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Employee getEmployee() { return employee; } public void setEmployee(Employee employee) { this.employee = employee; } public Long getEmployee_id() { return employee_id; } public void setEmployee_id(Long employee_id) { this.employee_id = employee_id; } }
- 同步静态方法在Java中如何工作?
- configurationHibernate通过JNDI数据源连接到数据库
- java.lang.ClassNotFoundException:org.hibernate.HibernateException
- 我发现JPA,或类似的,不鼓励DAO模式
- 如何使用REST API进行身份validation? (浏览器+本机客户端)
- 如何使用Hibernate打印带有参数值的查询string
- 错误:java.lang.NoSuchMethodError:org.objectweb.asm.ClassWriter。<init>(I)V
- Hibernate与iBATIS
- 如何通过在Hibernate中使用限制和标准来实现“不在”?