Como crear una vista de tabla en JPA

1,442 views
Skip to first unread message

Leandro Spadaro

unread,
Feb 1, 2012, 5:28:00 PM2/1/12
to (Grupo Java Google) Lista, Grupo Java BS AS, Grupo Java Mexico Java
Buenas,

Estoy probando de crear una vista de una tabla, para luego ordenar el resultado que determine el Select esa vista.
Esto es asi por que originalmente el Select terminaba con una clausula Order By lo que daba como resultado que 
la consulta se demorara mucho unos 17 segundos, sacando la clausula Order By se demora 2 segundos.

Probé haciendo una vista en SQL (con el SQL que arma EclipseLink) de la tabla y ordenar esa vista y se demora 2 segundos.
Pero cuando trato de armar la vista en JPA me da un error, lo que no encuentro o no se si JPA soporta Vista.

em.createQuery("SELECT gv"
                    + " FROM GestionValidacion gv, IN (gv.gestionValidacionSector) gvs"
                    + " WHERE gvs.numeroGestionSector = (SELECT MAX (gvs1.numeroGestionSector)"
                    + "                                  FROM GestionValidacion gv1, IN (gv1.gestionValidacionSector) gvs1"
                    + "                                  WHERE gv1.id = gv.id"
                    + "                                 )"
                    + " AND gvs.sectorDerivado.id = :idSector
                    + " ORDER BY gv.numeroGestionValidacion").
                    setParameter("idSector", idSector).
                    setFirstResult(inicio).
                    setMaxResults(cantidadRegistros).
                    getResultList();

Necesito que esa consulta se demore poco, alguien tiene alguna idea. Entra pr indices quiere decir que el problema
de la demora pasa por el Order BY.

Alguien tiene alguna idea que me ayude. Estuve pensando utilizar el operador JPQL NEW de JPA 2.0 pero busco otras alternativas.

Esta es la consulta en JPA que me da el error:  (SELECT......), line 1, column 17: unexpected token [(].
No le gustan los paréntesis en el FROM

          em.createQuery("SELECT gv2"
                                + "  FROM (SELECT gv.id as id"
                                + "        FROM GestionValidacion gv, IN (gv.gestionValidacionSector) gvs"
                                + "        WHERE gvs.numeroGestionSector = (SELECT MAX (gvs1.numeroGestionSector) "
                                + "                                           FROM GestionValidacion gv1, IN (gv1.gestionValidacionSector) gvs1"
                                + "                                          WHERE gv1.id = gv.id"
                                + "                                        )"
                                + "          AND gvs.sectorDerivado.id = :idSector"
                                + "       ) vista, GestionValidacion gv2"
                                + " WHERE gv2.id = vista.id"
                                + " ORDER BY gv.numeroGestionSector").
                                setParameter("idSector", idSector).
                                setFirstResult(inicio).
                                setMaxResults(cantidadRegistros).
                                getResultList();

Este es el SQL que funciona con la vista

SELECT
  G.*
 FROM ( SELECT 
             t1.ID
            FROM GESTIONVALIDACION_GESTIONVALIDACIONSECTOR t3, SECTOR t2, GESTIONVALIDACION t1, GESTIONVALIDACIONSECTOR t0
            WHERE (((t0.NUMEROGESTIONSECTOR = (SELECT MAX(t4.NUMEROGESTIONSECTOR)
                                      FROM GESTIONVALIDACION_GESTIONVALIDACIONSECTOR t7, GESTIONVALIDACION t6, GESTIONVALIDACION t5, GESTIONVALIDACIONSECTOR t4
                                     WHERE (((t5.ID = t6.ID)
                                       AND (t1.ID = t6.ID))
                                       AND ((t7.GestionValidacion_ID = t5.ID)
                                       AND (t4.ID = t7.gestionValidacionSector_ID)))))
              AND (t2.ID = 'idSectorDefecto6d4501af-7990-4cec-9106-6a5063b21c98'))
              AND (((t3.GestionValidacion_ID = t1.ID)
              AND (t0.ID = t3.gestionValidacionSector_ID))
              AND (t2.ID = t0.SECTORDERIVADO_ID)))
           ) VISTA, GESTIONVALIDACION G, 
WHERE VISTA.id = G.id
ORDER BY G.NUMEROGESTIONVALIDACION;

Nick Risaro

unread,
Feb 1, 2012, 9:12:07 PM2/1/12
to jav...@googlegroups.com, Grupo Java BS AS, Grupo Java Mexico Java
Creo que nunca trabajé con vistas en JPA, en hibernate puro tenés que mapearlas a un objeto, por ahí es por eso que da error tu consulta.

De todos modos una vista no va a mejorar tu performance, salvo que sea una vista materializada pero ahí ya nos vamos del standar.

Otro tema es que no todas las bases soportan un select en el from, pero eso no tiene nada que ver con una vista.

Espero haberos iluminado ;)

2012/2/1 Leandro Spadaro <leo_s...@hotmail.com>

--
www.JavaSOS.com
Grupo de colaboración Java/J2ee para desarrolladores de habla hispana.

Luis Alejandro Santana

unread,
Feb 2, 2012, 5:01:44 PM2/2/12
to jav...@googlegroups.com
Buenas Tardes,
 
Así es!, Nick Risaro tiene razón.  Es sabido que una vista, mapeada a través del archivo .hbm o a través de anotaciones dentro de la clase persistente, nos dará un mejor desempeño de nuestra aplicación que las consultas tradicionales.  Te sugiero que leas un poco sobre los mapeos de estas vistas a través de la clase o el archivo hbm.xml de tu persistencia.
 
Por ejemplo:
 
Caso 1. HBM.XML
 
<hibernate-mapping>
  <class name="Persistencia.Emp" schema="SYSTEM" table="EMP">
    <id name="empno" type="short">
      <column name="EMPNO" precision="4" scale="0"/>
      <generator class="assigned"/>
    </id>
    <property name="ename" type="string">
      <column length="10" name="ENAME"/>
    </property>
    <property name="job" type="string">
      <column length="9" name="JOB"/>
    </property>
    <property name="mgr" type="java.lang.Short">
      <column name="MGR" precision="4" scale="0"/>
    </property>
    <property name="hiredate" type="date">
      <column length="7" name="HIREDATE"/>
    </property>
    <property name="sal" type="big_decimal">
      <column name="SAL" precision="7"/>
    </property>
  </class>
    <sql-query name="empleadosPorManager">
        <return alias="empleado" class="Persistencia.Emp"/>
        select * from Emp e where e.mgr = :manager
    </sql-query>

</hibernate-mapping>
 
Caso 2. Persistencia.CLASS
 
@NamedQueries({ //HQL NAMED QUERY
            @NamedQuery(
            name="fechaDeContratacion",
            query="select emp.ename, emp.hiredate from Emp as emp where emp.hiredate >= :fecha"
            )
})
@NamedNativeQueries({ //SQL NAMED QUERY
 @NamedNativeQuery(
 name = "empPorNombre",
 query = "select * from Emp s where s.ename = :nombreEmpleado",
        resultClass = Emp.class
 )
})
@Entity
@Table(name="EMP"
    ,schema="SYSTEM"
)
public class Emp  implements java.io.Serializable {
      Aqui van los getters y setters de la clase persistente.
}
 
":nombreEmpleado", dentro del uso de los dos puntos en JPA, se utiliza en este caso para hacer un escape al String que le sigue después de los dos puntos, y asi reconocerlo como un pámetro que se le esta pasando a la consulta.
 
Espero te sirva de ayuda,
 
Saludos!,
--

Luis Alejandro Santana Valdez

Consultor Técnico-Funcional SAP  -  Desarrollador JAVA

Cel. 829-301-7407


Reply all
Reply to author
Forward
0 new messages