it-swarm.com.de

org.hibernate.TransientObjectException: object verweist auf eine nicht gespeicherte transiente Instanz. Speichern Sie die transiente Instanz vor dem Leeren

In meinem Projekt habe ich User, Role, UserRole und BloodGroup Entitäten. Zuerst nehme ich List<BloodGroup> von der DB und setze auf User. Dann gebe ich User und Role Entities an UserRole. Danach füge ich User in DB ein, dann versuche ich UserRole einzufügen, erhalte aber einen Fehler. Wenn ich mir die Datenbank anschaue, wird die ID von BloodGroup nicht in die User-Tabelle eingefügt.

Wenn ich das erste BloodGroup in der Liste wähle, erhalte ich eine Fehlermeldung. Andere Optionen sind normal.

Ich schaue auf das Internet, ich fand cascade = CascadeType.ALL, aber dies füge dieselben Daten zu BloodGroup hinzu, was bedeutet, dass ich mehr Arh + BloodGroup habe.

Die Entitäten:

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

}

Regler:

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);
}

Log:

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)
20
eaktas

ihr Problem wird gelöst, indem Sie kaskadierende Abhängigkeiten richtig definieren oder die referenzierten Entitäten speichern, bevor Sie die Entität speichern, auf die verwiesen wird. Das Definieren von Kaskadieren ist aufgrund der subtilen Variationen in der Verwendung wirklich schwierig, um richtig zu werden.

So können Sie Kaskaden definieren:

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

}

In diesem Szenario werden bei jedem Speichern, Aktualisieren, Löschen usw. der Benutzerrolle die zugehörigen Rollen und Benutzer ebenfalls gespeichert und aktualisiert.

Wenn Ihr Anwendungsfall verlangt, dass Sie Benutzer oder Rollen beim Aktualisieren von Userrole nicht ändern, speichern Sie einfach Benutzer oder Rollen, bevor Sie die Userrole ändern

Darüber hinaus haben bidirektionale Beziehungen einen unidirektionalen Besitz. In diesem Fall besitzt der Benutzer die Blutgruppe. Kaskaden gehen daher nur von Benutzer -> Blutgruppe aus. Sie müssen den Benutzer erneut in der Datenbank speichern (anhängen oder nicht flüchtig machen), um ihn mit Bloodgroup zu verknüpfen.

41
John Ericksen

Ich hatte ein ähnliches Problem und obwohl ich sichergestellt habe, dass referenzierte Entitäten zuerst gespeichert wurden, schlägt sie mit derselben Ausnahme fehl. Nach stundenlangen Nachforschungen stellt sich heraus, dass das Problem darin bestand, dass die Spalte "Version" der referenzierten Entität NULL war. In meinem speziellen Setup habe ich sie zuerst in eine HSQLDB (das war ein Komponententest) eingefügt Reihe wie das:

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

Das Problem des obigen Problems ist, dass die von hibernate verwendete Versionsspalte auf null gesetzt wurde. Selbst wenn das Objekt korrekt gespeichert wurde, betrachtet Hibernate es als nicht gespeichert. Als sichergestellt wurde, dass die Version einen NON-NULL-Wert (in diesem Fall 1) hatte, verschwand die Ausnahme und alles funktionierte einwandfrei.

Ich stelle es hier für den Fall vor, dass jemand anderes das gleiche Problem hatte, da dies eine lange Zeit dauerte, um dies herauszufinden, und die Lösung ist völlig anders als die oben genannte.

11
isaac.hazan

Ich habe dieses Problem mit dem Hinzufügen von @Cascade zum Attribut @ManyToOne behoben.

import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;

@ManyToOne
@JoinColumn(name="BLOODGRUPID")
@Cascade({CascadeType.MERGE, CascadeType.SAVE_UPDATE})
private Bloodgroup bloodgroup;
1

In meinem Fall, wenn Sie das referenzierte Objekt in meinem Objekt auf NULL setzen, bevor die Zusammenführungs- oder Speichermethode das Problem löst, in meinem Fall war das referenzierte Objekt Katalog, das nicht gespeichert werden muss, da ich es in einigen Fällen nicht habe sogar.

    fisEntryEB.setCatStatesEB(null);

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

Anstatt das Referenzobjekt durch das gespeicherte Objekt zu übergeben, finden Sie eine Erklärung, die mein Problem löst:

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

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