2012-02-05 17 views
19

En mi proyecto tengo User, Role, UserRole y BloodGroup entidades. En primer lugar, tomo List<BloodGroup> de DB y lo configuro en User. Luego doy User y Role entites a UserRole. Después de eso inserto User a DB, luego trato de insertar UserRole, pero me sale un error. Cuando miro a DB, la ID de BloodGroup no se inserta en la tabla User.org.hibernate.TransientObjectException: referencias a objetos de una instancia transitoria no salva - guardar la instancia transitoria antes de enjuagar

Si elijo el primer BloodGroup en la lista, aparece un error. Otras opciones son normales

Miro internet, encontré cascade = CascadeType.ALL, pero esto agrega los mismos datos a BloodGroup, lo que significa que tengo más Arh + BloodGroup.

Las entidades:

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

} 

controlador:

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) 
+0

Podría dar el código que arroja el error? solo para ver cómo está guardando las instancias. – ivowiblo

+2

En lugar de intentar encontrar cosas al azar encontradas en Internet, debe intentar comprender qué significa el error, detectar dónde se produce la excepción y corregir el error. Muéstrenos la traza completa de la pila y el código que causa esta excepción. –

Respuesta

39

su problema será resuelto por definir adecuadamente depedencies en cascada o por el ahorro de las entidades referenciadas antes de guardar la entidad que las referencias. La definición de la conexión en cascada es realmente difícil de lograr debido a todas las variaciones sutiles en la forma en que se utilizan.

Así es como se puede definir cascadas:

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

} 

En este escenario, cada vez que guarde, actualizar, eliminar, etc UserRole, también se guardarán el papel assocaited y el Usuario, actualizado ...

De nuevo, si su caso de uso exige que no modifique usuario o rol al actualizar UserRole, a continuación, simplemente guardar usuario o función antes de modificar UserRole

Además, las relaciones bidireccionales tienen una propiedad de una sola vía. En este caso, el usuario es dueño de Bloodgroup. Por lo tanto, las cascadas solo se realizarán desde Usuario -> Grupo sangriento. Nuevamente, debe guardar el usuario en la base de datos (adjuntarlo o hacerlo no transitorio) para asociarlo con Bloodgroup.

10

Tuve un problema similar y, aunque me aseguré de que las entidades a las que se hacía referencia se guardaran primero, sigue fallando con la misma excepción. Después de horas de investigación, resulta que el problema se debía a que la columna "versión" de la entidad a la que se hacía referencia era NULA. En mi configuración particular que estaba insertando primero en un HSQLDB (que era una prueba de unidad) una fila así:

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

El problema de lo anterior es la columna versión utilizada por hibernación se fijó a nulo, por lo incluso si el objeto se guardó correctamente, Hibernate lo consideró como no guardado. Al asegurarse de que la versión tuviera un valor NON-NULL (1 en este caso), la excepción desapareció y todo funcionó bien.

Lo estoy poniendo aquí en caso de que alguien más tenga el mismo problema, ya que esto me llevó mucho tiempo resolver esto y la solución es completamente diferente a la anterior.

+2

Hibernate siempre da los peores mensajes de error ... la pesadilla de mi vida laboral ... – Serge

+1

Gracias por esta respuesta ... el mismo problema me acaba de arrancar el pelo ... Estaba intentando todo tipo de transacciones y opciones de cascada solo para encontrar que el problema era un campo de versión NULL ... no podría encontrar en ningún otro lado que documente este problema. –

+1

Gracias por esta respuesta: este también fue el caso conmigo, al crear un usuario con CommandLineRunner en el arranque de primavera (también tiene algunos valores con NULL, nunca habría adivinado que el objeto se considera no guardado en tal caso) – lenach87

1

He resuelto este problema al agregar @Cascade al atributo @ManyToOne.

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

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

En lugar de objeto de referencia que pasa pasado el objeto salvados, a continuación hay explicación que resolver mi problema:

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

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