Java org.hibernate.transientObject异常:对象引用未保存的临时实例-在刷新之前保存临时实例
在我的项目中,我有Java org.hibernate.transientObject异常:对象引用未保存的临时实例-在刷新之前保存临时实例,java,spring,hibernate,orm,Java,Spring,Hibernate,Orm,在我的项目中,我有User、Role、UserRole和BloodGroup实体。首先,我从数据库中获取List,并设置为User。然后,我将User和Role实体赋予UserRole。在这之后,我将User插入数据库,然后我尝试插入UserRole,但我得到了一个错误。当我查看DB时,BloodGroup的ID没有插入到User表中 如果我选择列表中的第一个BloodGroup,我会得到一个错误。其他选择是正常的 我看了一下互联网,发现了cascade=CascadeType.ALL,但这给B
User
、Role
、UserRole
和BloodGroup
实体。首先,我从数据库中获取List
,并设置为User
。然后,我将User
和Role
实体赋予UserRole
。在这之后,我将User
插入数据库,然后我尝试插入UserRole
,但我得到了一个错误。当我查看DB时,BloodGroup
的ID没有插入到User
表中
如果我选择列表中的第一个BloodGroup
,我会得到一个错误。其他选择是正常的
我看了一下互联网,发现了cascade=CascadeType.ALL
,但这给BloodGroup
添加了相同的数据,这意味着我有更多的Arh+BloodGroup
实体:
@Entity
@Table(name="USERS")
public class User implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private long userid;
@OneToMany(mappedBy="user")
private List<Userrole> userroles;
//bi-directional many-to-one association to Bloodgroup
@ManyToOne
@JoinColumn(name="BLOODGRUPID")
private Bloodgroup bloodgroup;
}
控制器:
user.setBloodgroup(bloodGroupImpl.getBloodGroupById(bGroup));
user.setUserid(userImpl.insertUserProfile(user));
userRoleImpl.insertUserRole(user,role);
道:
日志:
您的问题将通过正确定义级联依赖关系或在保存引用的实体之前保存引用的实体来解决。定义级联确实很难做到正确,因为它们的使用方式有很多细微的变化 以下是如何定义级联:
@Entity
public class Userrole implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private long userroleid;
private Timestamp createddate;
private Timestamp deleteddate;
private String isactive;
//bi-directional many-to-one association to Role
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name="ROLEID")
private Role role;
//bi-directional many-to-one association to User
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name="USERID")
private User user;
}
在此场景中,每次保存、更新、删除等Userrole时,关联的角色和用户也将被保存、更新
同样,如果您的用例要求您在更新Userrole时不修改User或Role,那么只需在修改Userrole之前保存User或Role即可
此外,双向关系具有单向所有权。在这种情况下,用户拥有Bloodgroup。因此,级联将只从User->Bloodgroup开始。同样,您需要将用户保存到数据库中(附加它或使其非暂时性),以便将其与Bloodgroup关联。我遇到了类似的问题,尽管我确保先保存引用的实体,但它仍会失败,出现相同的异常。 经过数小时的调查,发现问题是因为引用实体的“版本”列为空。 在我的特定设置中,我首先将其插入HSQLDB(这是一个单元测试)中的一行,如下所示:
INSERT INTO project VALUES (1,1,'2013-08-28 13:05:38','2013-08-28 13:05:38','aProject','aa',NULL,'bb','dd','ee','ff','gg','ii',NULL,'LEGACY','0','CREATED',NULL,NULL,1,'0',NULL,NULL,NULL,NULL,'0','0', NULL);
上面的问题是hibernate使用的version列被设置为null,因此即使对象已正确保存,hibernate也会将其视为未保存。当确保版本具有非NULL(本例中为1)值时,异常消失,一切正常
我把它放在这里是为了防止其他人有同样的问题,因为我花了很长时间才弄明白,解决方案与上面的完全不同。我解决了这个问题,将@Cascade添加到@manytone属性中
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
@ManyToOne
@JoinColumn(name="BLOODGRUPID")
@Cascade({CascadeType.MERGE, CascadeType.SAVE_UPDATE})
private Bloodgroup bloodgroup;
下面是解决我的问题的解释,而不是将引用对象传递给已保存的对象:
//wrong
entityManager.persist(role);
user.setRole(role);
entityManager.persist(user)
//right
Role savedEntity= entityManager.persist(role);
user.setRole(savedEntity);
entityManager.persist(user)
在我的例子中,在merge o save方法解决问题之前,在我的对象中将被引用对象设置为NULL。在我的例子中,被引用对象是catalog,不需要保存,因为在某些情况下,我甚至没有它
fisEntryEB.setCatStatesEB(null);
(fisEntryEB) getSession().merge(fisEntryEB);
你能提供抛出错误的代码吗?只是想看看你是如何保存实例的。你应该试着理解错误的含义,检测异常抛出的位置,并修复错误,而不是尝试在internet上找到随机的东西。显示完整的堆栈跟踪和引发此异常的代码。这是否回答了您的问题?Hibernate总是给出最糟糕的错误消息。。。我工作生涯的祸根…谢谢你的回答。。。。同样的问题刚刚让我毛骨悚然。。。我尝试了各种事务和级联选项,结果发现问题是一个空版本字段。。。找不到记录此问题的其他地方。感谢您的回答-我也是这样,在spring boot中使用CommandLineRunner创建用户时(也有一些值为NULL,在这种情况下,绝对不会猜到对象被视为未保存)。谢谢,这个回答让我省去了很多麻烦+1.
INSERT INTO project VALUES (1,1,'2013-08-28 13:05:38','2013-08-28 13:05:38','aProject','aa',NULL,'bb','dd','ee','ff','gg','ii',NULL,'LEGACY','0','CREATED',NULL,NULL,1,'0',NULL,NULL,NULL,NULL,'0','0', NULL);
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
@ManyToOne
@JoinColumn(name="BLOODGRUPID")
@Cascade({CascadeType.MERGE, CascadeType.SAVE_UPDATE})
private Bloodgroup bloodgroup;
//wrong
entityManager.persist(role);
user.setRole(role);
entityManager.persist(user)
//right
Role savedEntity= entityManager.persist(role);
user.setRole(savedEntity);
entityManager.persist(user)
fisEntryEB.setCatStatesEB(null);
(fisEntryEB) getSession().merge(fisEntryEB);