7 Replies Latest reply on Feb 18, 2008 2:46 PM by gavin.king

    Problem persisting chils class

    rmcalderero.rmcalderero.wanadoo.es

      In our model we have a class A and a child class A1. When we persist an A1 instance with JPA/Hibernate in a junit test case the object is persisted correctly.


      However when execute exactly the same code with the entity manager indide a seam conversation the operation fails with this exception:


      Hibernate: insert into Analisis (descripcion, diaSemana, emailsAdicionales, envioEmailIndicadores, envioInformeEmail, envioSMSIndicadores, estado, fecha, informeEmail, movilSMS, nombre, periodo, id) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
      
      22:52:29,209 WARN  [JDBCExceptionReporter] SQL Error: 0, SQLState: S1009
      
      22:52:29,209 ERROR [JDBCExceptionReporter] Statement parameter 13 not set.
      
      22:52:29,224 ERROR [SeamPhaseListener] uncaught exception
      
      javax.el.ELException: javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: could not insert: [org.fundacionctic.tawmonitor.model.AnalisisCerrado]
      
           at org.jboss.el.util.ReflectionUtil.invokeMethod(ReflectionUtil.java:332)
      
           at org.jboss.el.util.ReflectionUtil.invokeMethod(ReflectionUtil.java:341)
      
           at org.jboss.el.parser.AstPropertySuffix.invoke(AstPropertySuffix.java:58)
      
      ..........................
      
           at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:87)
      
           at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:38)
      
           at org.hibernate.impl.SessionImpl.firePersist(SessionImpl.java:618)
      
           at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:592)
      
           at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:596)
      
           at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:213)
      
           ... 70 more
      
      Caused by: java.sql.SQLException: Statement parameter 13 not set.
      
           at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:910)
      
           at com.mysql.jdbc.ServerPreparedStatement.serverExecute(ServerPreparedStatement.java:1045)
      
           at com.mysql.jdbc.ServerPreparedStatement.executeInternal(ServerPreparedStatement.java:693)
      
           at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1404)
      
           at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1318)
      
           at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1303)
      
           at org.hibernate.id.IdentityGenerator$GetGeneratedKeysDelegate.executeAndExtract(IdentityGenerator.java:73)
      
           at org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:33)
      
           ... 85 more
      
      
      


      The problem is the id attribute inside the insert statement created by seam. This attribute is annotated @Id @GeneratedValue and obviously is no set in our instance; it must me managed by hibernate.


      So is there some special consideration in Seam when persisting parent/child objects?


        • 1. Re: Problem persisting chils class
          msystems

          Please show us some code, e.g. 'class A', 'child class A1' and the code where you persist the A1 instance.

          • 2. Re: Problem persisting chils class
            rmcalderero.rmcalderero.wanadoo.es

            OK, this is our parent class Analisis:


            package org.fundacionctic.tawmonitor.model;
            
            
            import java.util.ArrayList;
            
            import java.util.Date;
            
            import java.util.List;
            
            
            import javax.persistence.CascadeType;
            
            import javax.persistence.Entity;
            
            import javax.persistence.GeneratedValue;
            
            import javax.persistence.Id;
            
            import javax.persistence.Inheritance;
            
            import javax.persistence.InheritanceType;
            
            import javax.persistence.JoinColumn;
            
            import javax.persistence.ManyToMany;
            
            import javax.persistence.ManyToOne;
            
            import javax.persistence.OneToMany;
            
            import javax.persistence.Transient;
            
            
            import org.hibernate.validator.NotNull;
            
            
            @Entity
            
            @Inheritance(strategy=InheritanceType.JOINED)
            
            public abstract class Analisis implements java.io.Serializable {
            
            
                 // public static String ESTADO_PENDIENTE = "pendiente";
            
            
                 public static String ESTADO_APROBADO = "aprobado";
            
                 public static String ESTADO_SUSPENDIDO = "suspendido";
            
                 
            
                 private int id;
            
            
                 private UsuarioFuncional usuario;
            
            
                 private String nombre;
            
            
                 private String descripcion;
            
            
                 private Date fecha;
            
            
                 private String periodo;
            
            
                 private int diaSemana;
            
            
                 private boolean envioInformeEmail;
            
                 
            
                 private String informeEmail;
            
                 
            
                 private String emailsAdicionales;
            
            
                 private boolean envioEmailIndicadores;
            
            
                 private boolean envioSMSIndicadores;
            
            
                 private String movilSMS;
            
            
                 private String estado = ESTADO_APROBADO;
            
            
                 private List<Indicador> indicadores = new ArrayList<Indicador>();
            
            
                 private List<ResultadoAnalisis> resultadosAnalisis = new ArrayList<ResultadoAnalisis>();
            
            
                 public Analisis() {
            
                 }
            
            
                 public Analisis(Analisis analisis) {
            
            
                      this.id = analisis.getId();
            
                      this.nombre = analisis.getNombre();
            
                      this.descripcion = analisis.getDescripcion();
            
                      this.fecha = analisis.getFecha();
            
                      this.periodo = analisis.getPeriodo();
            
                      this.diaSemana = analisis.getDiaSemana();
            
                      this.envioInformeEmail = analisis.getEnvioInformeEmail();
            
                      this.informeEmail = analisis.getInformeEmail();
            
                      this.emailsAdicionales = analisis.getEmailsAdicionales();
            
                      this.envioEmailIndicadores = analisis.isEnvioEmailIndicadores();
            
                      this.envioSMSIndicadores = analisis.isEnvioSMSIndicadores();
            
                      this.movilSMS = analisis.getMovilSMS();
            
                      this.estado = analisis.getEstado();
            
                      this.indicadores = new ArrayList<Indicador>();
            
                      for(Indicador indicador: analisis.getIndicadores()) {
            
                           Indicador nuevoIndicador = new Indicador(indicador);
            
                           this.indicadores.add(nuevoIndicador);
            
                      }
            
                      
            
            
                 }
            
                 
            
                 
            
                 @NotNull
            
                 public String getDescripcion() {
            
                      return descripcion;
            
                 }
            
            
                 public void setDescripcion(String descripcion) {
            
                      this.descripcion = descripcion;
            
                 }
            
            
                 @NotNull
            
                 public int getDiaSemana() {
            
                      return diaSemana;
            
                 }
            
            
                 public void setDiaSemana(int diaSemana) {
            
                      this.diaSemana = diaSemana;
            
                 }
            
            
                 @NotNull
            
                 public boolean isEnvioEmailIndicadores() {
            
                      return envioEmailIndicadores;
            
                 }
            
            
                 public void setEnvioEmailIndicadores(boolean envioEmailIndicadores) {
            
                      this.envioEmailIndicadores = envioEmailIndicadores;
            
                 }
            
            
                 @NotNull
            
                 public boolean getEnvioInformeEmail() {
            
                      return envioInformeEmail;
            
                 }
            
            
                 public void setEnvioInformeEmail(boolean envioInformeEmail) {
            
                      this.envioInformeEmail = envioInformeEmail;
            
                 }
            
            
                 public String getInformeEmail() {
            
                      return informeEmail;
            
                 }
            
            
                 public void setInformeEmail(String informeEmail) {
            
                      this.informeEmail = informeEmail;
            
                 }
            
            
                 @NotNull
            
                 public boolean isEnvioSMSIndicadores() {
            
                      return envioSMSIndicadores;
            
                 }
            
            
                 public void setEnvioSMSIndicadores(boolean envioSMSIndicadores) {
            
                      this.envioSMSIndicadores = envioSMSIndicadores;
            
                 }
            
            
                 @NotNull
            
                 public String getEstado() {
            
                      return estado;
            
                 }
            
            
                 public void setEstado(String estado) {
            
                      this.estado = estado;
            
                 }
            
            
                 @NotNull
            
                 public Date getFecha() {
            
                      return fecha;
            
                 }
            
            
                 public void setFecha(Date fecha) {
            
                      this.fecha = fecha;
            
                 }
            
            
                 @Id @GeneratedValue
            
                 public int getId() {
            
                      return id;
            
                 }
            
            
                 public void setId(int id) {
            
                      this.id = id;
            
                 }
            
                 
            
                 @ManyToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE })
            
                 public List<Indicador> getIndicadores() {
            
                      return indicadores;
            
                 }
            
            
                 public void setIndicadores(List<Indicador> indicadores) {
            
                      this.indicadores = indicadores;
            
                 }
            
            
                 public String getMovilSMS() {
            
                      return movilSMS;
            
                 }
            
            
                 public void setMovilSMS(String movilSMS) {
            
                      this.movilSMS = movilSMS;
            
                 }
            
            
                 @NotNull
            
                 public String getNombre() {
            
                      return nombre;
            
                 }
            
            
                 public void setNombre(String nombre) {
            
                      this.nombre = nombre;
            
                 }
            
            
                 @NotNull
            
                 public String getPeriodo() {
            
                      return periodo;
            
                 }
            
            
                 public void setPeriodo(String periodo) {
            
                      this.periodo = periodo;
            
                 }
            
            
                 @OneToMany(cascade = CascadeType.ALL)
            
                 @JoinColumn(name="analisis_id") 
            
                 public List<ResultadoAnalisis> getResultadosAnalisis() {
            
                      return resultadosAnalisis;
            
                 }
            
            
                 public void setResultadosAnalisis(List<ResultadoAnalisis> resultados) {
            
                      this.resultadosAnalisis = resultados;
            
                 }
            
            
                 @ManyToOne
            
                 @JoinColumn(name="usuario_id", insertable=false, updatable=false)
            
                 public UsuarioFuncional getUsuario() {
            
                      return usuario;
            
                 }
            
            
                 public void setUsuario(UsuarioFuncional usuario) {
            
                      this.usuario = usuario;
            
                 }
            
            
                 public String getEmailsAdicionales() {
            
                      return emailsAdicionales;
            
                 }
            
            
                 public void setEmailsAdicionales(String emailsAdicionales) {
            
                      this.emailsAdicionales = emailsAdicionales;
            
                 }
            
                 
            
            }
            
            


            And the child class AnalisisCerrado:



            package org.fundacionctic.tawmonitor.model;
            
            
            import java.util.ArrayList;
            
            import java.util.List;
            
            
            import javax.persistence.CascadeType;
            
            import javax.persistence.Entity;
            
            import javax.persistence.JoinColumn;
            
            import javax.persistence.OneToMany;
            
            import javax.persistence.Transient;
            
            
            import org.jboss.seam.annotations.Name;
            
            
            @Entity
            
            @Name("analisisCerrado")
            
            public class AnalisisCerrado extends Analisis implements java.io.Serializable {
            
            
                 private List<UrlAnalisis> urls = new ArrayList<UrlAnalisis>();
            
            
                 public AnalisisCerrado() {
            
                 }
            
            
                 public AnalisisCerrado(AnalisisCerrado analisisCerrado) {
            
                      
            
                      super(analisisCerrado);
            
                      
            
                      this.urls = new ArrayList<UrlAnalisis>();
            
                      for(UrlAnalisis urlAnalisis: analisisCerrado.getUrls()) {
            
                           UrlAnalisis nuevaUrlAnalisis = new UrlAnalisis(urlAnalisis);
            
                           nuevaUrlAnalisis.setAnalisisCerrado(this);
            
                           this.urls.add(nuevaUrlAnalisis);
            
                      }
            
                 }
            
                 
            
                 @OneToMany(cascade = CascadeType.ALL)
            
                 @JoinColumn(name="analisisCerrado_id") 
            
                 public List<UrlAnalisis> getUrls() {
            
                      return urls;
            
                 }
            
            
                 public void setUrls(List<UrlAnalisis> urls) {
            
                      this.urls = urls;
            
                 }
            
            
            }
            
            



            OK, and this is the code that works correctly with the test case and fails within the seam conversation:



                      AnalisisCerrado analisisCerradoPrueba = new AnalisisCerrado();
            
                      analisisCerradoPrueba.setNombre("Prueba");
            
                      analisisCerradoPrueba.setDescripcion("---");
            
                      analisisCerradoPrueba.setFecha(new Date());
            
                      analisisCerradoPrueba.setPeriodo(PerfilFuncional.PERIODO_QUINCENAL);
            
                      analisisCerradoPrueba.setDiaSemana(1);
            
                      analisisCerradoPrueba.setEnvioInformeEmail(true);
            
                      analisisCerradoPrueba.setEnvioEmailIndicadores(false);
            
                      analisisCerradoPrueba.setEnvioSMSIndicadores(false);
            
                      
            
                      em.persist(analisisCerradoPrueba);



            In other conversations of our application we can persist other non-child entities.

            • 3. Re: Problem persisting chils class

              The problem is the id attribute inside the insert statement created by seam. This attribute is annotated @Id @GeneratedValue and obviously is no set in our instance; it must me managed by hibernate.


              id, in this case, is always 'set' to number, since an int can't be null. It is kind of strange that the insert clause has 13 '?' but hibernate only has set 12 variables. What happens if you use Integer?

              • 4. Re: Problem persisting chils class
                rmcalderero.rmcalderero.wanadoo.es

                Thank you Daniel, you were right !!


                When we changed the type of the id attribute to Integer, sean correctly persisted the child instance.


                BTW we are using 2.0.0.GA. Is this a bug ?? In all other normal entities we have the identifiers typed as int not Integer, working ok. And even in the test case the child instance is persisted with the id as int. So it seems there is some kind of issue with the way seam manages identifiers in parent/child entities.

                • 5. Re: Problem persisting chils class

                  Nice :-)


                  If it is a bug, probably any of the Seam developers should answer.


                  However, using primitive types as @Id could be a bit complicated since it has an initial value which is not null (and thereby could be an actual id).


                  I'm still a bit confused why it wasn't set in the query. Maybe inserts are only done if id==null?

                  • 6. Re: Problem persisting chils class
                    gavin.king

                    Looks like a question for the Hibernate forum. I guess it has nothing to do with Seam, perhaps some subtle config difference in the appserver environment.

                    • 7. Re: Problem persisting chils class
                      gavin.king

                      However, using primitive types as @Id could be a bit complicated since it has an initial value which is not null (and thereby could be an actual id).

                      This is all supposed to be handled by Hibernate's unsaved-value detection stuff. Should not be a problem.


                      Perhaps the id is somehow getting set to a nonzero value, before or after persist() is called.