web-dev-qa-db-ja.com

org.hibernate.TransientObjectException:オブジェクトは保存されていない一時インスタンスを参照しています-フラッシュする前に一時インスタンスを保存します

私のプロジェクトには、UserRoleUserRole、およびBloodGroupエンティティがあります。まず、List<BloodGroup> DBからUserに設定します。それからUserRoleUserRoleに誘います。その後、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<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)
21
eaktas

カスケード依存関係を適切に定義するか、参照するエンティティを保存する前に参照するエンティティを保存することにより、問題が解決されます。カスケードの定義は、使用方法の微妙な違いがあるため、正しく行うのは本当に難しいです。

カスケードを定義する方法は次のとおりです。

@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;

}

このシナリオでは、ユーザーロールを保存、更新、削除などするたびに、関連付けられたロールとユーザーも保存、更新されます...

繰り返しますが、ユーザーロールを更新するときにユーザーまたはロールを変更しないようにユースケースが要求する場合は、ユーザーロールを変更する前にユーザーまたはロールを保存するだけです

さらに、双方向の関係には一方向の所有権があります。この場合、ユーザーはBloodgroupを所有しています。したがって、カスケードはユーザー->血液型からのみ続行します。繰り返しますが、ユーザーをBloodgroupに関連付けるには、ユーザーをデータベースに保存する(アタッチするか、非一時的にする)必要があります。

41
John Ericksen

同様の問題があり、参照されたエンティティが最初に保存されていることを確認しましたが、同じ例外で失敗し続けます。数時間の調査の後、参照されたエンティティの「バージョン」列が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)値が含まれていることを確認すると、例外が消え、すべてが正常に機能しました。

他の誰かが同じ問題を抱えている場合に備えて、ここに置いています。これを理解するのに長い時間がかかり、解決策は上記とは完全に異なっているからです。

11
isaac.hazan

@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;
1

私の場合、マージo saveメソッドの前にオブジェクトの参照オブジェクトをNULLに設定すると、問題が解決します。私の場合、参照オブジェクトはカタログでしたが、保存する必要はありません。でも。

    fisEntryEB.setCatStatesEB(null);

    (fisEntryEB) getSession().merge(fisEntryEB);
0
Axel Osorio

参照オブジェクトを渡すのではなく、保存したオブジェクトを渡すのではなく、以下が私の問題を解決する説明です。

//wrong
entityManager.persist(role);
user.setRole(role);
entityManager.persist(user)

//right
Role savedEntity= entityManager.persist(role);
user.setRole(savedEntity);
entityManager.persist(user)
0