Menu

OX3 e hibernate tools

2007-12-13
2012-11-26
  • Jose Enrique

    Jose Enrique - 2007-12-13

    Hola, se me ha ocurrido probar a generar las entidades ejb con hibernate-tools a partir de un modelo en base de datos. Desde OX-3.0beta4 ejecuto las tareas ant y luego al hacer la prueba desde el navegador no me encuentra ningún módulo. El log sólo me dice "Organización no es una entidad EJB3 ni una clase transitoria".

    ¿Alguien lo ha probado?. Os paso una de las clases de ejemplo por si alguien aprecia alguna anomalía:

    package org.openxava.montes.modelo;

    // Generated 13-dic-2007 19:07:42 by Hibernate Tools 3.2.0.CR1

    import java.math.BigDecimal;
    import java.util.HashSet;
    import java.util.Set;
    import javax.persistence.CascadeType;
    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.FetchType;
    import javax.persistence.Id;
    import javax.persistence.OneToMany;
    import javax.persistence.Table;

    /**
    * Organizacion generated by hbm2java
    */
    @Entity
    @Table(name = "ORGANIZACION", schema = "MONTES")
    public class Organizacion implements java.io.Serializable {

        private BigDecimal idOrganizacion;
        private String nombre;
        private String nombreS;
        private Set<Personal> personals = new HashSet<Personal>(0);

        public Organizacion() {
        }

        public Organizacion(BigDecimal idOrganizacion) {
            this.idOrganizacion = idOrganizacion;
        }

        public Organizacion(BigDecimal idOrganizacion, String nombre,
                String nombreS, Set<Personal> personals) {
            this.idOrganizacion = idOrganizacion;
            this.nombre = nombre;
            this.nombreS = nombreS;
            this.personals = personals;
        }

        @Id
        @Column(name = "ID_ORGANIZACION", unique = true, nullable = false, precision = 22, scale = 0)
        public BigDecimal getIdOrganizacion() {
            return this.idOrganizacion;
        }

        public void setIdOrganizacion(BigDecimal idOrganizacion) {
            this.idOrganizacion = idOrganizacion;
        }

        @Column(name = "NOMBRE", length = 100)
        public String getNombre() {
            return this.nombre;
        }

        public void setNombre(String nombre) {
            this.nombre = nombre;
        }

        @Column(name = "NOMBRE_S", length = 100)
        public String getNombreS() {
            return this.nombreS;
        }

        public void setNombreS(String nombreS) {
            this.nombreS = nombreS;
        }

        @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "organizacion")
        public Set<Personal> getPersonals() {
            return this.personals;
        }

        public void setPersonals(Set<Personal> personals) {
            this.personals = personals;
        }

    }

     
    • Javier Paniza

      Javier Paniza - 2007-12-14

      Hola José Enrique,

      > Organización no es una entidad EJB3 ni una clase transitoria
      ¿No séra por el acento?

      > ¿Alguien lo ha probado?.
      He probado tu clase y funciona perfectamente.
      Esto es lo que he hecho, usando OX3beta4:
      1. He creado un proyecto Montes desde OpenXavaPlantilla.
      2. He copiado tu clase tal cual (bueno, le he quitado el esquema).
      3. He creado una clase Personal
      4. He ejecutado updateSchema contra una DB hypersonic virgen.
      5. He arrancado mi Tomcat (desde WTP).
      6. He ejecutado la aplicación, dando altas de Organizaciones que su personal

      Todo me ha funcionado.
      La clase Personal que he escrito es así:

      package org.openxava.montes.modelo;

      import javax.persistence.*;

      import org.openxava.annotations.*;

      @Entity
      @View(members="nombre")
      public class Personal {
         
          @ManyToOne
          private Organizacion organizacion;
         
          @Id @Column(length=5)
          @GeneratedValue(strategy=GenerationType.IDENTITY)
          private Integer id;
         
          @Column(length=20) @Required
          private String nombre;

          public Organizacion getOrganizacion() {
              return organizacion;
          }

          public void setOrganizacion(Organizacion organizacion) {
              this.organizacion = organizacion;
          }

          public Integer getId() {
              return id;
          }

          public void setId(Integer id) {
              this.id = id;
          }

          public String getNombre() {
              return nombre;
          }

          public void setNombre(String nombre) {
              this.nombre = nombre;
          }

      }

      No sé porque te fallará, pero la clase Organizacion parece estar bien.
      Trata de seguir los mismos pasos que yo, a ver si descubres algo.

      Dime cómo te va. Tu experimento parece muy interesante.

      Saludos
      Javi

       
    • Jose Enrique

      Jose Enrique - 2007-12-14

      jejeje... lo del acento es porque he transcrito manualmente la salida de consola en lugar de hacer un copiapega... de todos modos estoy viendo que el problema no tiene nada que ver con las anotaciones y debe ser bastante más trivial pues he visto que por algún motivo hibernate no consigue la conexión con Oracle. Me he creado un jsp de prueba que lee el datasource definido en context.xml y me abro una conexión sin correctamente...

      Bueno, el problema no tiene nada que ver con el asunto de modo que intentaré encontrar donde tengo el error y al menos postearé qué tal me ha ido con hibernate tools.

       
    • Jose Enrique

      Jose Enrique - 2007-12-17

      Pues no es un problema de conexiones (el log es un tanto ambigo al respecto y en apariencia indicaba no consegui una conexión hibernate). He probado a eliminar todas las entidades y reducir el testeo sólo a 2 (eliminando relaciones con otras tablas). Como tablas independientes sí me funciona, pero en cuanto hago uso de las anotaciones que genera hibernate tools para relacionar tablas me falla.

      Si intento consultar el módulo "Organizacion" el error es:

      17-dic-2007 14:26:01 org.openxava.component.ComponentParser parseAnnotatedClass
      GRAVE: null
      java.lang.NullPointerException
          at org.openxava.annotations.parse.AnnotatedClassParser.addReference(AnnotatedClassParser.java:241)
          at org.openxava.annotations.parse.AnnotatedClassParser.addMember(AnnotatedClassParser.java:128)
          at org.openxava.annotations.parse.AnnotatedClassParser.parseMembers(AnnotatedClassParser.java:106)
          at org.openxava.annotations.parse.AnnotatedClassParser.addAggregateForCollection(AnnotatedClassParser.java:195)
          at org.openxava.annotations.parse.AnnotatedClassParser.processAnnotations(AnnotatedClassParser.java:886)
          at org.openxava.annotations.parse.AnnotatedClassParser.addCollection(AnnotatedClassParser.java:157)
          at org.openxava.annotations.parse.AnnotatedClassParser.addMember(AnnotatedClassParser.java:129)
          at org.openxava.annotations.parse.AnnotatedClassParser.parseMembers(AnnotatedClassParser.java:106)
          at org.openxava.annotations.parse.AnnotatedClassParser.parse(AnnotatedClassParser.java:76)
          at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      ...
      ...

      Si por el contrario trato de consultar el módulo "Personal" el error reza así:

      17-dic-2007 14:26:01 org.openxava.component.ComponentParser parseAnnotatedClass
      GRAVE: Imposible analizar el EJB3 con anotaciones Organizacion
      org.openxava.util.XavaException: Imposible analizar el EJB3 con anotaciones Organizacion
          at org.openxava.component.ComponentParser.parseAnnotatedClass(ComponentParser.java:58)
          at org.openxava.component.ComponentParser.parse(ComponentParser.java:34)
          at org.openxava.component.MetaComponent.get(MetaComponent.java:60)
          at org.openxava.model.meta.MetaReference.getMetaModelReferenced(MetaReference.java:104)
          at org.openxava.annotations.parse.AnnotatedClassParser.addReference(AnnotatedClassParser.java:224)
          at org.openxava.annotations.parse.AnnotatedClassParser.addMember(AnnotatedClassParser.java:128)
          at org.openxava.annotations.parse.AnnotatedClassParser.parseMembers(AnnotatedClassParser.java:106)
          at org.openxava.annotations.parse.AnnotatedClassParser.parse(AnnotatedClassParser.java:76)
          at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
          at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
          at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
          at java.lang.reflect.Method.invoke(Unknown Source)
          at org.openxava.util.Objects.execute(Objects.java:193)
          at org.openxava.util.Objects.execute(Objects.java:112)
          at org.openxava.component.ComponentParser.parseAnnotatedClass(ComponentParser.java:54)
      ...
      ...

      Por comodidad también he pasado a realizar las pruebas con hypersonic. Estas son las clases:

      package org.openxava.montes.modelo;

      // Generated 14-dic-2007 13:34:43 by Hibernate Tools 3.2.0.CR1

      import java.math.BigDecimal;
      import java.util.HashSet;
      import java.util.Set;
      import javax.persistence.CascadeType;
      import javax.persistence.Column;
      import javax.persistence.Entity;
      import javax.persistence.FetchType;
      import javax.persistence.Id;
      import javax.persistence.OneToMany;
      import javax.persistence.Table;

      /**
      * Organizacion generated by hbm2java
      */
      @Entity
      @Table(name = "ORGANIZACION")
      public class Organizacion implements java.io.Serializable {

          private BigDecimal idOrganizacion;
          private String nombre;
          private String nombreS;
          private Set<Personal> personals = new HashSet<Personal>(0);

          public Organizacion() {
          }

          public Organizacion(BigDecimal idOrganizacion) {
              this.idOrganizacion = idOrganizacion;
          }

          public Organizacion(BigDecimal idOrganizacion, String nombre,
                  String nombreS, Set<Personal> personals) {
              this.idOrganizacion = idOrganizacion;
              this.nombre = nombre;
              this.nombreS = nombreS;
              this.personals = personals;
          }

          @Id
          @Column(name = "ID_ORGANIZACION", unique = true, nullable = false, precision = 22, scale = 0)
          public BigDecimal getIdOrganizacion() {
              return this.idOrganizacion;
          }

          public void setIdOrganizacion(BigDecimal idOrganizacion) {
              this.idOrganizacion = idOrganizacion;
          }

          @Column(name = "NOMBRE", length = 100)
          public String getNombre() {
              return this.nombre;
          }

          public void setNombre(String nombre) {
              this.nombre = nombre;
          }

          @Column(name = "NOMBRE_S", length = 100)
          public String getNombreS() {
              return this.nombreS;
          }

          public void setNombreS(String nombreS) {
              this.nombreS = nombreS;
          }

          @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "organizacion")
          public Set<Personal> getPersonals() {
              return this.personals;
          }

          public void setPersonals(Set<Personal> personals) {
              this.personals = personals;
          }

      }

      package org.openxava.montes.modelo;

      // Generated 14-dic-2007 13:34:43 by Hibernate Tools 3.2.0.CR1

      import java.math.BigDecimal;
      import java.util.HashSet;
      import java.util.Set;
      import javax.persistence.AttributeOverride;
      import javax.persistence.AttributeOverrides;
      import javax.persistence.CascadeType;
      import javax.persistence.Column;
      import javax.persistence.EmbeddedId;
      import javax.persistence.Entity;
      import javax.persistence.FetchType;
      import javax.persistence.JoinColumn;
      import javax.persistence.JoinTable;
      import javax.persistence.ManyToMany;
      import javax.persistence.ManyToOne;
      import javax.persistence.OneToMany;
      import javax.persistence.Table;
      import javax.persistence.UniqueConstraint;

      /**
      * Personal generated by hbm2java
      */
      @Entity
      @Table(name = "PERSONAL", uniqueConstraints = {
              @UniqueConstraint(columnNames = "USUARIO"),
              @UniqueConstraint(columnNames = "FK_ID_CONTACTO") })
      public class Personal implements java.io.Serializable {

          private PersonalId id;
          private Organizacion organizacion;
          private String cargo;
          private String usuario;
          private String pwd;
          private BigDecimal tipAuth;

          public Personal() {
          }

          public Personal(PersonalId id, Organizacion organizacion) {
              this.id = id;
              this.organizacion = organizacion;
          }

          public Personal(PersonalId id,
                  Organizacion organizacion, String cargo, String usuario,
                  String pwd, BigDecimal tipAuth) {
              this.id = id;
              this.organizacion = organizacion;
              this.cargo = cargo;
              this.usuario = usuario;
              this.pwd = pwd;
              this.tipAuth = tipAuth;
          }

          @EmbeddedId
          @AttributeOverrides( {
                  @AttributeOverride(name = "idOrganizacion", column = @Column(name = "ID_ORGANIZACION", nullable = false, precision = 22, scale = 0)) })
          public PersonalId getId() {
              return this.id;
          }

          public void setId(PersonalId id) {
              this.id = id;
          }

          @ManyToOne(fetch = FetchType.LAZY)
          @JoinColumn(name = "ID_ORGANIZACION", nullable = false, insertable = false, updatable = false)
          public Organizacion getOrganizacion() {
              return this.organizacion;
          }

          public void setOrganizacion(Organizacion organizacion) {
              this.organizacion = organizacion;
          }

          @Column(name = "CARGO", length = 80)
          public String getCargo() {
              return this.cargo;
          }

          public void setCargo(String cargo) {
              this.cargo = cargo;
          }

          @Column(name = "USUARIO", unique = true, length = 100)
          public String getUsuario() {
              return this.usuario;
          }

          public void setUsuario(String usuario) {
              this.usuario = usuario;
          }

          @Column(name = "PWD")
          public String getPwd() {
              return this.pwd;
          }

          public void setPwd(String pwd) {
              this.pwd = pwd;
          }

          @Column(name = "TIP_AUTH", precision = 22, scale = 0)
          public BigDecimal getTipAuth() {
              return this.tipAuth;
          }

          public void setTipAuth(BigDecimal tipAuth) {
              this.tipAuth = tipAuth;
          }

      }

      package org.openxava.montes.modelo;

      // Generated 14-dic-2007 13:34:43 by Hibernate Tools 3.2.0.CR1

      import java.math.BigDecimal;
      import javax.persistence.Column;
      import javax.persistence.Embeddable;

      /**
      * PersonalId generated by hbm2java
      */
      @Embeddable
      public class PersonalId implements java.io.Serializable {

          private BigDecimal idOrganizacion;
          private BigDecimal fkIdContacto;

          public PersonalId() {
          }

          public PersonalId(BigDecimal idOrganizacion, BigDecimal fkIdContacto) {
              this.idOrganizacion = idOrganizacion;
              this.fkIdContacto = fkIdContacto;
          }

          @Column(name = "ID_ORGANIZACION", nullable = false, precision = 22, scale = 0)
          public BigDecimal getIdOrganizacion() {
              return this.idOrganizacion;
          }

          public void setIdOrganizacion(BigDecimal idOrganizacion) {
              this.idOrganizacion = idOrganizacion;
          }

          @Column(name = "FK_ID_CONTACTO", unique = true, nullable = false, precision = 22, scale = 0)
          public BigDecimal getFkIdContacto() {
              return this.fkIdContacto;
          }

          public void setFkIdContacto(BigDecimal fkIdContacto) {
              this.fkIdContacto = fkIdContacto;
          }

          public boolean equals(Object other) {
              if ((this == other))
                  return true;
              if ((other == null))
                  return false;
              if (!(other instanceof PersonalId))
                  return false;
              PersonalId castOther = (PersonalId) other;

              return ((this.getIdOrganizacion() == castOther.getIdOrganizacion()) || (this
                      .getIdOrganizacion() != null
                      && castOther.getIdOrganizacion() != null && this
                      .getIdOrganizacion().equals(castOther.getIdOrganizacion())))
                      && ((this.getFkIdContacto() == castOther.getFkIdContacto()) || (this
                              .getFkIdContacto() != null
                              && castOther.getFkIdContacto() != null && this
                              .getFkIdContacto().equals(castOther.getFkIdContacto())));
          }

          public int hashCode() {
              int result = 17;

              result = 37
                      * result
                      + (getIdOrganizacion() == null ? 0 : this.getIdOrganizacion()
                              .hashCode());
              result = 37
                      * result
                      + (getFkIdContacto() == null ? 0 : this.getFkIdContacto()
                              .hashCode());
              return result;
          }

      }

      ... seguiré intentándolo pues sería todo el esqueleto a una aplicación OX3 a partir de las clases generadas con hibernate tools y el modelo de datos.

       
      • Javier Paniza

        Javier Paniza - 2007-12-18

        Hola José Enrique,

        encontré el problema. Es un bug de OX3beta4.
        Muy fácil de arreglar.
        Ve a la línea 240 de la clase AnnotatedClassParser,
        y cambia :
        JoinColumn joinColumn = field.getAnnotation(JoinColumn.class);
        por:
        JoinColumn joinColumn = pd.getReadMethod().getAnnotation(JoinColumn.class);

        Simplemente preguntaba sí tenía la anotación en el getter, y después la
        intentaba leer del atributo privado (field). Esto me pasa porque todos los POJOs
        que escrito en OX3 los tengo anotando los atributos en vez de las propiedades.

        Haz este cambio y me dices que tal te va.
        Yo ya lo he modificado y estará arreglado para la beta5,
        además he revisado el resto del código buscando un problema similar
        y parece que este era el único caso.

        Saludos
        Javi

         
    • Jose Enrique

      Jose Enrique - 2007-12-17

      ... tanto en la clase Personal como en PersonalId he eliminado toda referencia a FK_ID_CONTACTO (antes he cometido un gazapo)...

       
    • Jose Enrique

      Jose Enrique - 2007-12-18

      Biiiingo!!! funciona perfectamente Javier. Antes de leer tu post te iba a comentar que sólo me fallaba en relaciones de muchos a muchos y que en general estaba contento con tener desplegado todo un esquema de base de datos en Open Xava a falta de corregir manualmente dichas relaciones fijándome en OpenXavaTest... pero he llevado a cabo la modificación que me has indicado y me ha entrado la risa floja... es genial!

      Respecto a las anotaciones que hace hibernate-tools sólo he tenido problemas con campos tipo blob. Seguramente mediante algún ajuste del tipo de dicha propiedad se solucione para el caso de una DB hypersonic, pero yo voy a centrarme en Oracle. Abriré otro post para Oracle por otro tipo de problemas, pero la primera sensación que he tenido al ver 34 entidades desplegadas fácilmente en OpenXava con CRUD ha sido estupenda... OX3 promete, ahora me toca documentarme, testear y si pudiera aportar algo útil así lo haré.

      Saludos.

       
      • Javier Paniza

        Javier Paniza - 2007-12-19

        Hola José Enrique,

        > la primera sensación que he tenido al ver 34 entidades desplegadas fácilmente en OpenXava con CRUD ha sido estupenda
        No sabes cuanto me alegra oir eso.
        De hecho, uno de los motivos para evolucionar hacía POJOs, en vez de XML, era
        eso, poder utilizar herramientas de terceros. Fíjate lo que digo aquí sobre la versión 3:
        http://www.gestion400.com/web/guest/future

        Tenía ganas de probar lo que tus has hecho, pero no he tenido una buena ocasión para hacerlo,
        así que me encanta que lo hayas hecho, y encima el resultado haya sido bueno.

        > si pudiera aportar algo útil así lo haré
        Una cosa muy interesante sería que añadieras una guía en el wiki:
        http://openxava.wiki.sourceforge.net/

        sobre como convertir una base de datos existente en una aplicación OX3
        con hibernate tools. No es necesario que sea una guía detallada, si lo es mejor
        claro, pero con que pongas algunas sugerencias y trucos ya sería algo valioso.

        O también escribir un pequeño artículo y publicarlo en javahispano o algo así.

        Estos son solo ideas, haz lo que te apetezca, o puedas.

        Saludos
        Javi

         
    • Jose Enrique

      Jose Enrique - 2008-01-03

      Un pequeño problema que estoy teniendo es que por algún motivo fallan las anotaciones para clases que implementan claves primarias. Hibernate tools utiliza @EmbeddedId en la clase de entidad en lugar de @IdClass, y en la clase "key" la anotación @Embeddable. No sé porqué falla pero es una lástima porque es muy cómodo y elegante, ya que a diferencia de las IdClass sólo tienes que implementar los atributos en la clase @Embeddable (y no en las dos) y en la clase entidad hacer referencia al Id. Esto se agradece sobre todo cuando la clave está compuesta por varios campos. El caso es que  en el modo tab funciona perfectamente pero en el detalle no es capaz de obtener la clave y presenta el formulario vacío y con un error.

      La solución es modificar estas clases usando @IdClass como se hace por ejemplo en TransportCharge2Key de OpenXavaTest... ¿alguien lo ha probado? no sé a qué achacar éste error pero he encontrado un hilo en un foro donde pasa algo parecido al usar estas anotaciones http://forums.java.net/jive/thread.jspa?threadID=17026

       
      • Javier Paniza

        Javier Paniza - 2008-01-04

        Hola José Enrique,

        > ... @EmbeddedId ... No sé porqué falla pero es una lástima ...
        Pues falla porque no está implementado en OX3. De momento solo se reconoce @IdClass

        Me lo he apuntado para que esté disponible para la versión 3.0 final (o antes).

        http://sourceforge.net/tracker/index.php?func=detail&aid=1863833&group_id=123187&atid=695746

        Si quieres puedes echarle un vistazo a la clase AnnotatedClassParser,
        si te atreves puede añadir tú mismo el soporte. Si no, no te preocupes,
        me lo miraré. La verdad, es que me parece muy interesante que OX3
        reconozca lo mejor posible el código que genera hibernate tools.

        Saludos
        Javi

         
        • Javier Paniza

          Javier Paniza - 2008-02-06

          Hola José Enrique,

          pues la versión OX3.0beta5, que ya está disponible, soporta @EmbeddedId.
          Te invito a que la pruebes.

          Saludos
          Javi

           
    • Jose Enrique

      Jose Enrique - 2008-02-19

      Testeado!! funciona muy bien, gracias Javi

       

Log in to post a comment.