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

时间:2012-02-05 13:16:23

标签: java spring hibernate orm

在我的项目中,我有UserRoleUserRoleBloodGroup个实体。首先,我从数据库中取List<BloodGroup>并设置为User。然后我将UserRole entites给UserRole。之后我将User插入到DB中,然后我尝试插入UserRole,但是我收到错误。当我查看数据库时,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;

}

@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<User> 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)

5 个答案:

答案 0 :(得分:41)

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

以下是如何定义级联:

@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。因此,级联将仅从用户进行 - &gt; Bloodgroup。同样,您需要将用户保存到数据库中(将其附加或使其成为非瞬态),以便将其与Bloodgroup相关联。

答案 1 :(得分:11)

我遇到了类似的问题,虽然我确保首先保存了引用的实体,但它仍然会出现相同的异常。 经过数小时的调查后发现问题是因为&#34;版本&#34;引用实体的列为NULL。 在我的特定设置中,我首先将它插入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使用的版本列被设置为null,所以即使对象被正确保存,Hibernate也认为它是未保存的。当确保版本具有NON-NULL(在这种情况下为1)值时,异常消失并且一切正常。

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

答案 2 :(得分:1)

我解决了将@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;

答案 3 :(得分:0)

不是传递参考对象传递保存的对象,下面是解释我的问题的解释:

<?php 
$mpn = 'Ram Pukar';
$text_mpn = 'Hello ';
echo $text = !empty($mpn) ? '<span class="p-rewards">MPN: '.$text_mpn.'</span>'.$mpn.'<br />':null;
?>

答案 4 :(得分:0)

在我的情况下,在merge o save方法解决问题之前,在我的对象中将引用的对象设置为NULL,在我的情况下,引用的对象是目录,不需要保存,因为在某些情况下,我不需要甚至没有。

    fisEntryEB.setCatStatesEB(null);

    (fisEntryEB) getSession().merge(fisEntryEB);