org.hibernate.TransientObjectException:object引用未保存的瞬态实例 – 在刷新之前保存瞬态实例

在我的项目中,我有UserRoleUserRoleBloodGroup实体。 首先,我从DB中获取List并设置为User 。 然后我将UserRole entites给UserRole 。 之后我将User插入DB,然后我尝试插入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 userroles; //bi-directional many-to-one association to Bloodgroup @ManyToOne @JoinColumn(name="BLOODGRUPID") private Bloodgroup bloodgroup; } 

 @Entity public class Bloodgroup implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy=GenerationType.AUTO) private int bloodgroupid; private String bloodgroupname; @OneToMany(mappedBy="bloodgroup") private List users; } 

 @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 @JoinColumn(name="ROLEID") private Role role; //bi-directional many-to-one association to User @ManyToOne @JoinColumn(name="USERID") private User user; } 

控制器:

 user.setBloodgroup(bloodGroupImpl.getBloodGroupById(bGroup)); user.setUserid(userImpl.insertUserProfile(user)); userRoleImpl.insertUserRole(user,role); 

DAO:

 public void insertUserRole(User user, Role role) { Session session =getHibernateTemplate().getSessionFactory().getCurrentSession(); Userrole uRole = new Userrole(); uRole.setIsactive("1"); uRole.setRole(role); uRole.setUser(user); session.save(uRole); session.flush(); } public void insertUserProfile(User user) { Session session = getHibernateTemplate().getSessionFactory().getCurrentSession(); session.save(user); } 

日志:

 Hibernate: insert into IU.Userrole (userroleid, createddate, deleteddate, isactive, ROLEID, USERID) values (default, ?, ?, ?, ?, ?) 05.Şub.2012 19:23:29 com.sun.faces.application.ActionListenerImpl processAction SEVERE: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.iu.eblood.model.Bloodgroup javax.faces.el.EvaluationException: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.iu.eblood.model.Bloodgroup at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:102) at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102) at javax.faces.component.UICommand.broadcast(UICommand.java:315) at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:775) at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1267) at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:82) at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:103) at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118) at javax.faces.webapp.FacesServlet.service(FacesServlet.java:310) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:198) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:198) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:224) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98) at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:928) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407) at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:987) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:539) at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:300) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) at java.lang.Thread.run(Thread.java:662) 

您的问题将通过正确定义级联依赖关系或通过在保存引用的实体之前保存引用的实体来解决。 定义级联是非常棘手的,因为它们的使用方式存在细微变化。

以下是如何定义级联:

 @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时不修改用户或角色,则只需在修改Userrole之前保存用户或角色

此外,双向关系具有单向所有权。 在这种情况下,用户拥有Bloodgroup。 因此,级联只会从用户 – >血型进行。 同样,您需要将用户保存到数据库中(将其附加或使其成为非瞬态),以便将其与Bloodgroup相关联。

我有一个类似的问题,虽然我确保首先保存引用的实体,但它仍然失败,但同样的exception。 经过数小时的调查后发现问题是因为引用实体的“版本”列为NULL。 在我的特定设置中,我首先将它插入HSQLDB(这是一个unit testing),就像这样:

 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使用的版本列被设置为null,所以即使对象被正确保存,Hibernate也认为它是未保存的。 当确保版本具有NON-NULL(在这种情况下为1)值时,exception消失并且一切正常。

我把它放在这里以防其他人有同样的问题,因为这花了我很长时间才弄明白,解决方案与上述完全不同。

我解决了将@Cascade添加到@ManyToOne属性的问题。

 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,在我的情况下,引用的对象是目录,不需要保存,因为在某些情况下我没有它甚至。

  fisEntryEB.setCatStatesEB(null); (fisEntryEB) getSession().merge(fisEntryEB);