lunes, 21 de septiembre de 2009

Hibernate - Parte 7: HQL Primera Parte

Hibernate proporciona un lenguaje de consultas muy poderoso llamado "Hibernate Query Language" (HQL).

HQL es muy parecido al SQL estándar, con la diferencia de que es completamente orientado a objetos (usamos nombres de clases y sus atributos en lugar de nombres de tablas y columnas), por lo que podemos usar cosas como herencia, polimorfismo y asociaciones.

Nosotros escribimos las consultas en HQL y Hibernate se encarga de convertirlas al SQL usado por la base de datos con la que estemos trabajando y ejecutarla para realizar la operación indicada.

En este tutorial veremos cómo usar este lenguaje para hacer algunas consultas típicas dentro de nuestras aplicaciones para poder recuperar objetos simples, y arboles de objetos.

Lo primero que hay que saber sobre HQL es que es case-insensitive, o sea que sus sentencias pueden escribirse en mayúsculas y minúsculas. Por lo tanto "SeLeCt", "seleCT", "select", y "SELECT" se entienden como la misma cosa.

Lo único con lo que debemos tener cuidado es con los nombres de las clases que estamos recuperando y con sus propiedades, ahí si se distinguen mayúsculas y minúsculas. O sea, en este caso "pruebas.hibernate.Usuario" NO ES LO MISMO que "PrueBAs.HibernatE.UsuArio".

En este tutorial colocaré las clausulas HQL (SELECT, WHERE, ORDER BY, etc.) en mayúsculas.

Comencemos con el tutorial creando un nuevo proyecto en NetBeans.

Lo primero que haremos es crear un proyecto en NetBeans (menú "File -> New Project... -> Java -> Java Application"). Le damos un nombre y una ubicación al proyecto y nos aseguramos de que las opciones "Create Main Class" y "Set as Main Project" estén habilitadas. Presionamos el botón "Finish" y veremos aparecer nuestra clase "Main" en el editor.

En el tutorial usaremos anotaciones en vez de archivos de mapeo para que sea un poco más claro, así que agregamos las bibliotecas de "Hibernate" y "HibernateAnotaciones", que creamos en el primer y segundo tutoriales. Hacemos clic derecho en el nodo "Libraries" del proyecto y en el menú contextual que se abre seleccionamos la opción "Add Library...":



En la ventana que se abre seleccionamos las bibliotecas "Hibernate" y “HibernateAnotaciones”:



Presionamos el botón "Add Library" para que la biblioteca se agregue a nuestro proyecto. Aprovechamos también para agregar el conector de MySQL. Debemos tener los siguientes archivos en nuestro proyecto:



Ahora creamos un paquete con el nombre “modelo” que contendrá las clases entidad. Hacemos clic derecho en el nodo del paquete que se creó al generar el proyecto, en el menú contextual que se abre seleccionamos la opción "New -> Java Package..." y creamos el paquete.



Que debe quedar así:



Ahora crearemos el archivo de configuración, el cual será muy parecido al del segundo tutorial. Recuerden que este archivo debe llamarse "hibernate.cfg.xml" y debe encontrarse en la raíz del classpath del proyecto (el paquete default)



<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
   <session-factory>

       <!-- parametros para la conexion a la base de datos -->
       <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
       <property name="connection.url">jdbc:mysql://localhost:3306/hibernatehql</property>
       <property name="connection.username">root</property>
       <property name="connection.password">123</property>

       <!-- Configuracion del pool interno -->
       <property name="connection.pool_size">1</property>

       <!-- Dialecto de la base de datos -->
       <property name="dialect">org.hibernate.dialect.MySQL5Dialect</property>

       <!-- Otras propiedades importantes -->
       <property name="show_sql">true</property>
       <property name="hbm2ddl.auto">none</property>

       <!-- Aqui iran las clases entidades -->
      

   </session-factory>
</hibernate-configuration>


Por ahora dejaremos el archivo de configuración como está mientras creamos nuestras clases entidades:


Nuestras Entidades


Para este ejemplo crearemos tres clases entidad: "Usuario", "Direccion" y "Permiso". La relación que existirá sobre estas tres clases es una relación uno a uno entre "Usuario" y "Dirección" y una relación uno a muchos de "Usuario" con "Permiso"; o sea, un "Usuario" puede tener una "Dirección" y un "Usuario" puede tener muchos "Permisos".

Aunque estas relaciones son simples, nos ayudaran a mostrar las consultas que realizamos con mayor frecuencia en las aplicaciones.

Primero, crearemos la clase “Permiso”. Creamos una nueva clase en el paquete “modelo” con el siguiente contenido:

@Entity
@Table(name="permisos")
public class Permiso implements Serializable
{
    public enum Estatus {PENDIENTE, ACTIVO, INACTIVO};

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private long id;
    private String nombre;
    private Estatus estatus = Estatus.PENDIENTE;

    public Permiso()
    {
    }

    public Estatus getEstatus()
    {
        return estatus;
    }

    public void setEstatus(Estatus estatus)
    {
        this.estatus = estatus;
    }

    public long getId()
    {
        return id;
    }

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

    public String getNombre()
    {
        return nombre;
    }

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


La entidad “Permiso” es muy sencilla pero nos permitirá observar el comportamiento de las consultas HQL. Usa las anotaciones que expliqué en el segundo tutorial.

Noten que agregué una enum para restringir los valores de los estatus solo para ejemplificar en uso de las mismas dentro de las entidades.

La siguiente clase que crearemos es “Dirección”, creamos esta clase en el paquete “modelo”. Este clase mantendrá una relación uno a uno bidireccional con "Usuario". La clase queda de esta forma:

@Entity
@Table(name="direcciones")
public class Direccion implements Serializable
{
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private long id;
    private String calle;
    private String codigoPostal;

    @OneToOne(mappedBy="direccion")
    private Usuario usuario;

    public Direccion()
    {
    }

    public String getCalle()
    {
        return calle;
    }

    public void setCalle(String calle)
    {
        this.calle = calle;
    }

    public String getCodigoPostal()
    {
        return codigoPostal;
    }

    public void setCodigoPostal(String codigoPostal)
    {
        this.codigoPostal = codigoPostal;
    }

    public long getId()
    {
        return id;
    }

    protected void setId(long id)
    {
        this.id = id;
    }

    public Usuario getUsuario()
    {
        return usuario;
    }

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


Como dije antes: la clase “Direccion” mantiene una relación uno a uno bidireccional con la clase “Usuario” y, como lo indica el elemento “mappedBy” de la anotación @OneToOne, la entidad “Usuarioes la dueña de la relación.

Ahora veamos la clase “Usuario”.

Creamos la clase “Usuario” en el paquete “modelo”. Esta clase mantendrá la relación uno a muchos con “Permiso” y la relación uno a uno con “Direccion”; y queda de la siguiente forma:

@Entity
@Table(name="usuarios")
public class Usuario implements Serializable
{
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private long id;
    private String nombre;
    private String username;
    private String password;

    @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY)
    private List<Permiso> permisos = new ArrayList<Permiso>();

    @OneToOne(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
    private Direccion direccion;

    public long getId()
    {
        return id;
    }

    protected void setId(long id)
    {
        this.id = id;
    }

    public String getNombre()
    {
        return nombre;
    }

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

    public String getPassword()
    {
        return password;
    }

    public void setPassword(String password)
    {
        this.password = password;
    }

    public List<Permiso> getPermisos()
    {
        return permisos;
    }

    public void setPermisos(List<Permiso> permisos)
    {
        this.permisos = permisos;
    }

    public String getUsername()
    {
        return username;
    }

    public void setUsername(String username)
    {
        this.username = username;
    }

    public Direccion getDireccion()
    {
        return direccion;
    }

    public void setDireccion(Direccion direccion)
    {
        this.direccion = direccion;
        direccion.setUsuario(this);
    }
} 


Usuario” es una entidad muy similar a las que hemos visto a lo largo de estos tutoriales, así que no debería haber problemas para entenderla. Lo único interesante sobre son las relaciones que mantiene con las otras entidades.

Ahora que tenemos las entidades no olvidemos que debemos indicarlas en el archivo “hibernate.cfg.xml”:

<mapping class="hql.modelo.Permiso" />
<mapping class="hql.modelo.Usuario" />
<mapping class="hql.modelo.Direccion" />


Ahora que tenemos todo configurado comencemos propiamente con el tutorial.

Para los ejercicios usaremos una base de datos llamada "hibernatehql", en MySQL.

Lo siguiente que debemos saber sobre las consultas en HQL es que, como mencione antes, trabajamos usando los nombres de las clases; esto quiere decir que si tenemos una clase entidad llamada “Usuario” en el paquete “hql.modelo”, cuyos registros se guardan en una tabla “usuarios”, NO colocamos el nombre de la tabla en las consultas, sino el nombre de la clase. O sea en vez de hacer algo asi:


SELECT u.col_username FROM usuarios u…


Haríamos

SELECT u.username FROM hql.modelo.Usuario u…


O también podemos hacer:

SELECT u.username FROM Usuario u…


De la misma forma si el valor del atributo “username” del usuario se guarda en la columna “col_username” hacemos referencia a este valor con el nombre del atributo: “username” y no con el nombre de la columna.

Ahora veremos las clausulas con las que podemos formar una sentencia:


Características de HQL


Estas son algunas de las características más importantes que nos proporciona HQL:

  • Soporte completo para operaciones relacionales: HQL permite representar consultas SQL en forma de objetos. HQL usa clases y atributos o propiedades en vez de tablas y columnas.
  • Regresa sus resultados en forma de objetos: Las consultas realizadas usando HQL regresan los resultados de las mismas en la forma de objetos o listas de objetos, que son más fáciles de usar, ya que eliminan la necesidad de crear un objeto y llenarlo con los datos obtenidos de un ResultSet (como hacemos normalmente cuando trabajamos con JDBC).
  • Consultas Polimórficas: Podemos declarar el resultado usando el tipo de la superclase y Hibernate se encargara de crear los objetos adecuados de las subclases correctas de forma automática.
  • Fácil de Aprender: Es muy similar a SQL estándar, así que si has trabajado con SQL, HQL te resultará muy fácil.
  • Soporte para características avanzadas: HQL contiene muchas características avanzadas que son muy útiles y que no siempre están presentes en todas las bases de datos, o no es fácil usarlas, como paginación, fetch joins con perfiles dinámicos, inner y outer joins, etc. Además soporta proyecciones, funciones de agregación (max, avg), y agrupamientos, ordenamientos, y subconsultas.
  • Independiente del manejador de base de datos: Las consultas escritas en HQL son independientes de la base de datos (siempre que la base de dats soporte la característica que estamos intentando utilizar ^-^).

Bueno, ahora que sabemos un poco de HQL veamos cómo usarlo. Para ver los resultados arrojados por las consultas no necesitaremos crear una aplicación, ya que NetBeans nos permite ejecutar estas directamente desde un editor especial. Pero para usarlo debemos configurar algunas otras cosas, que explicaré a continuación.


Configurando el NetBeans para los ejemplos


Lo primero que debemos hacer es crear nuestra base de datos en MySQL con las tablas y datos de prueba necesarios. Creamos una base de datos llamada “hibernatehql” con cuatro tablas: “direcciones”, “permisos”, “usuarios”, y “usuarios_permisos”. Esta última tabla mantendrá las relaciones entre usuarios y permisos. Pueden usar el siguiente script para crear y poblar la base de datos, o si lo desean pueden descargarlo desde aquí:

CREATE DATABASE IF NOT EXISTS  `hibernatehql`;

USE `hibernatehql`;

/*Estructura de la tabla `direcciones` */

DROP TABLE IF EXISTS `direcciones`;

CREATE TABLE `direcciones` (                 
               `id` BIGINT(20) NOT NULL AUTO_INCREMENT,   
               `calle` VARCHAR(255) DEFAULT NULL,         
               `codigoPostal` VARCHAR(255) DEFAULT NULL,  
               PRIMARY KEY (`id`)                         
             ) ENGINE=INNODB DEFAULT CHARSET=latin1;    


/*Datos de la tabla `direcciones` */

insert  into `direcciones`(`id`,`calle`,`codigoPostal`) values (1,'Calle1','12345'),(2,'Calle2','54321');
/*Estructura de la tabla `permisos` */

DROP TABLE IF EXISTS `permisos`;

CREATE TABLE `permisos` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `estatus` int(11) DEFAULT NULL,
  `nombre` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1;

/*Datos de la tabla `permisos` */

insert  into `permisos`(`id`,`estatus`,`nombre`) values (1,0,'Lectura Archivos'),(2,0,'Creacion Archivos'),(3,1,'Eliminacion Archivos'),(4,1,'Moficacion Archivos'),(5,2,'Sin Permisos');

/*Estructura de la tabla `usuarios` */

DROP TABLE IF EXISTS `usuarios`;

CREATE TABLE `usuarios` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `nombre` varchar(255) DEFAULT NULL,
  `password` varchar(255) DEFAULT NULL,
  `username` varchar(255) DEFAULT NULL,
  `direccion_id` BIGINT(20) DEFAULT NULL,      
  PRIMARY KEY (`id`),                                                                         
  KEY `FK_DIRECCIONES` (`direccion_id`),                                                    
  CONSTRAINT `FK_DIRECCIONES` FOREIGN KEY (`direccion_id`) REFERENCES `direcciones` (`id`)  
  ) ENGINE=INNODB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;          
  

/*Datos de la tabla `usuarios` */

insert  into `usuarios`(`id`,`nombre`,`password`,`username`,`direccion_id`) values (1,'Usuario 1','abcdefg','usr001',1),(2,'Usuario1','hijklm','usr456',2),(3,'Usuario3','alex','alex',null);
/*Estructura de la tabla `usuarios_permisos` */

DROP TABLE IF EXISTS `usuarios_permisos`;

CREATE TABLE `usuarios_permisos` (
  `usuarios_id` bigint(20) NOT NULL,
  `permisos_id` bigint(20) NOT NULL,
  UNIQUE KEY `permisos_id` (`permisos_id`),
  KEY `FK_USUARIOS` (`usuarios_id`),
  KEY `FK_PERMISOS` (`permisos_id`),
  CONSTRAINT `FK_PERMISOS` FOREIGN KEY (`permisos_id`) REFERENCES `permisos` (`id`),
  CONSTRAINT `FK_USUARIOS` FOREIGN KEY (`usuarios_id`) REFERENCES `usuarios` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

/*Datos de la tabla `usuarios_permisos` */

INSERT  INTO `usuarios_permisos`(`usuarios_id`,`permisos_id`) VALUES (1,1),(1,2),(2,3),(2,4),(3,5);


Ahora vayamos al NetBeans.

Anteriormente, cuando instalamos plugins en el NetBeans y lo configuramos para usar el tomcat, usamos un panel llamado “Services”, el cual nos permite agregar servicos y herramientas externas (servidores web y de aplicaciones, bases de datos, servicios web, etc.) para tener acceso a ellos dentro de NetBeans.

En esta ocasión agregaremos un servicio que nos permitirá tener una conexión a nuestra base de datos de prueba.



En el panel “Services” hacemos clic derecho sobre el nodo “Databases” y en el menú contextual que se abre seleccionamos la opción “New Connection…



Con lo que se abrirá la ventana “New Database Connection”. En esta ventana podemos escribir directamente la URL de la conexión (jdbc:mysql://…), o escribir algunos parámetros y dejar que la URL se genere automáticamente. Nosotros haremos este último.

Lo primero que hacemos es seleccionar, en el campo “Name” la opción “MySQL (Connector/J driver)”. El resto de los datos se obtienen de su conexión a su servidor de base de datos.



Usen los datos propios de su servidor para conectarse. Al final, con los datos de mi conexión, la ventana queda así:



Les recomiendo que habiliten la opción “Remember password” y “Show JDBC URL”. Hacemos clic en el botón “OK” y veremos que en el panel “Services”, en el nodo “Databases” aparecerá la conexión a nuestra base de datos. En caso de que haya un error aparecerá el mensaje correspondiente para que podamos corregirlo.



Gracias a esta configuración ahora podremos ejecutar sentencias de SQL directamente en NetBeans:



Pero, lo más importante, es que también podemos ejecutar sentencias HQL desde el NetBeans, sin necesidad de crear una aplicación:



Será esta forma en la que ejecutaremos las clausulas durante este tutorial.

Veremos las clausulas más comunes de este lenguaje y haremos ejemplos usando nuestras entidades.


La clausula FROM


La clausula más simple que existe en Hibernate es “FROM”. Esta clausula regresa todas las instancias de la clase indicada que se encuentran en la base de datos, es como si hiciéramos un “SELECT *” en MySQL. Por ejemplo, para recuperar todos los usuarios de la base de datos ejecutamos la consulta de esta forma:

FROM hql.modelo.Usuario


Normalmente no necesitamos el “fully qualified name” de la clase, así que esta misma sentencia podríamos escribirla de esta forma:

FROM Usuario


Al ejecutar esta sentencia en NetBeans, con los datos de la base de pruebas que creamos, obtendremos el siguiente resultado:



Dentro de esta clausula FROM podemos colocar el nombre de más de una clase, lo que resultará en un producto cartesiano entre las entidades que coloquemos. Podemos colocar el nombre de dos de nuestras entidades en la clausula, de esta forma:

FROM Usuario, Permiso


Resultando en la siguiente salida:



Aquí se muestra un todos contra todos (producto cartesiano) ya que no colocamos ninguna restricción en cuanto a las condiciones que deben cumplir los objetos.

Cuando tenemos que referirnos a nuestras clases en otras partes de la consulta, como en las restricciones, debemos asignarle un alias y hacer referencia a la clase a través de este alias. No podemos usar directamente el nombre del objeto ya que resultaría en una excepción. Por ejemplo, continuando con la consulta anterior, si quisiéramos hacer referencia al “id” del “Usuario”, si lo hacemos de esta forma:

FROM Usuario, Permiso WHERE Usuario.id = 1


Obtendríamos la siguiente excepción:



En vez de esto debemos asignarle un alias a la clase entidad "Usuario" y hacer referencia a los atributos de esta entidad usando el alias, de esta forma:

FROM Usuario as u, Permiso WHERE u.id = 1


O así:

FROM Usuario u, Permiso WHERE u.id = 1


Resultando en la salida esperada:




Asociaciones y Joins


HQL también permite los siguientes cuatro tipos de joins entre entidades:

  • Inner Join
  • Left Outer Join
  • Right Outer Join
  • Full Join (siempre que la base de datos que estemos usando los soporte)

Además también podemos asignar alias a las entidades asociadas o a los elementos de una colección de valores usando un join, por ejemplo:

FROM Usuario u inner join u.permisos as p


Con su correspondiente salida



También podemos proporcionar condiciones extra al join con la palabra reservada WITH:

FROM Usuario u inner join u.permisos as p WITH p.estatus = 1




La parte que voy a explicar es muy importante y nos resultará muy útil cuando trabajemos con colecciones de objetos. ¿Recuerdan que cuando vimos las relaciones uno a muchos, dije que en la relación podemos indicar la forma de fetch o recuperación de los elementos de la colección? ¿Y que estos tipos solo son 2: EAGER y LAZY?

Cuando tenemos una colección con tipo de fetch EAGER no hay problema, al recuperar la entidad recuperaremos también todos los objetos de la colección. Pero ¿qué ocurre cuando el tipo de fetch es LAZY? En ese caso necesitamos recuperar los elementos de la colección de otra forma.

Pues bien, esto puede hacerse usando un tipo especial de join llamado "fetch" join, el cual nos permite inicializar los elementos de estas asociaciones o colecciones. Este fetch join “sobreescribe” la declaración de fetch LAZY de la colección (solo para la consulta que se está realizando).

Por ejemplo, nosotros tenemos en nuestra entidad "Usuario" declarada la lista de permisos de la siguiente forma:

@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY)
private List<Permiso> permisos = new ArrayList<Permiso>();


Esto quiere decir que cuando recuperemos, ya dentro de una aplicación, al Usuario, sus permisos no serán recuperados e inicializados en ese momento. Esto es útil si estamos, por ejemplo, mostrando una lista de usuarios y no nos interesa mostrar nada relacionado con sus permisos en ese momento. Pero ¿qué ocurre cuando el usuario ingresa a la aplicación y nos interesa validar los permisos que tiene? En ese caso si debemos recuperar la lista de permisos. Pues bien, es para esto que nos sirve el fetch join, y se usa de la siguiente forma:

FROM Usuario u inner join fetch u.permisos


Recuerden que aunque la instrucción se llama fetch join la usamos al revés ("join fetch"). Y con esto se recuperarán los permisos del usuario al mismo tiempo que el usuario. En el editor de HQL de NetBeans esto no se logra apreciar bien, pero créanme, cuando estén realizando una aplicación esto puede salvarnos la vida ^-^.




Sintaxis de los joins


HQL soporta dos sintaxis para los joins: implícita y explícita.

En los ejemplos anteriores hemos estado usando la forma explícita, o sea, que colocamos la palabra join dentro de la clausula. Esta es la forma recomendada ya que es más clara, sin embargo si queremos ahorrar un poco de espacio podemos usar la forma implícita de esta manera:



Como vemos, ocurre un join implícito entre "Usuario" y "Dirección", usando el atributo dirección de la clase Usuario. Lo malo de este tipo de joins es que solo puede hacerse cuando tenemos una relación uno a uno o muchos a uno, o sea, no funciona cuando la propiedad es una colección:




Preguntando por el Identificador


En HQL existen dos formas de referirnos a la propiedad que sirve como identificador de la entidad:

  • La propiedad especial “id” (así con minúsculas). No importa si la clase entidad no tiene una propiedad llamada id.
  • Si la entidad define una propiedad identificador, podemos referirnos a ella a través del nombre de dicha propiedad (en el caso de estos ejemplos la propiedad identificadora es llamada id, así que no me será posible ejemplificar esto claramente).

Importante: Esto quiere decir que si nuestra entidad tiene un atributo llamado “id”, pero esto no es el identificador de la entidad, no habrá forma de hacer referencia a él.


La clausula SELECT


La clausula SELECT indica cuáles objetos y propiedades se regresarán en el conjunto de resultados de la consulta (así es, podemos regresar solamente algunas propiedades de los objetos y no todo el objeto, pero esto lo veremos más adelante).

Supongamos que tenemos la siguiente consulta:

SELECT dir FROM Usuario as u inner join u.direccion as dir


Esta consulta regresará la direccion de los usuarios. Podemos expresar esta misma consulta de una forma más compacta haciendo uso de los joins implícitos:

SELECT u.direccion FROM Usuario as u




Como dije hace un momento: podemos recuperar solo algunos atributos o valores del objeto que estemos regresando. Por ejemplo, la siguiente consulta regresa solo el nombre del usuario:

SELECT u.nombre FROM Usuario as u


En la ventana de ejecución del HQL en el NetBeans, vemos el resultado de esta forma:



Intentaré dar una explicación al porqué se ven de esta forma los datos. Si me equivoco en la explicación por favor corríjanme.

Cuando recuperamos solo un atributo de un objeto, recuperamos una lista de objetos del tipo del atributo que queremos recuperar (si es String recuperamos Strings, si es int recuperamos ints, etc.).

Sin embargo, si recuperamos más de un atributo de un objeto, Hibernate NO nos regresa una lista del tipo de objeto (en este caso "Usuario"), si no que nos regresa una lista de arreglos de objetos, o sea, una lista en la que cada uno de los elementos es un arreglo de objetos. Cada uno de los objetos del arreglo representa uno de los valores recuperados. Como nosotros solo estamos recuperando el valor de una propiedad (el nombre del usuario) vemos que en el NetBeans solo tenemos un valor en cada fila (no tengo idea de porqué muestra varias filas). Como Hibernate no sabe (o no le importa) el tipo del objeto que es el valor del atributo cuando lo regresa, solo que es un objeto, nos regresa un arreglo de bytes (finalmente todo objeto es un arreglo de bytes) y es esto lo que vemos en los valores regresados (cuando tenemos que un valor empieza solo con un corchete que abre ([) significa que el valor es un arreglo.

Como supongo que algunos de ustedes no me creerán que esto funciona, tendré que demostrarlo en código ^_^.

Como siempre, usaremos la clase HibernateUtil desarrollada antes, la del segundo tutorial, ya que estamos trabajando con anotaciones.

Como vamos a hacer varios pequeños ejemplos, crearemos un método para cada uno y lo invocaremos en el constructor de la clase Main. Después iremos comentando y des-comentando las invocaciones a los métodos para ver su funcionamiento individual.

Además crearemos un atributo de instancia en nuestra clase Main que nos ayudará a manejar las conexiones en todos los métodos. Esta variable será de tipo “org.hibernate.Session”, la declararemos de esta forma:

private Session sesion;


Y dos métodos de utilidad. El primero creará una nueva sesión a la base de datos e iniciar una transacción. El segundo método terminará la transacción y cerrará la conexión.

Este es el método que inicia la sesión:

private void inciaOperacion()
{
        SessionFactory sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
        sesion = sessionFactory.openSession();
        sesion.getTransaction().begin();
}


Y este es el método que la termina:

private void terminaOperacion()
{
        sesion.getTransaction().commit();
        sesion.close();
}


Ahora crearemos el método que recuperará solo el nombre del usuario haciendo uso de la consulta anterior.

Hasta ahora no habíamos realizado consultas con HQL, así que tendré que explicar cómo usarlas en código.

Con Hibernate normalmente haremos consultas el HQL (también podemos hacer consultas en el SQL de la base de datos que estemos usando, pero no hablaré de eso). Para ejecutar una consulta en HQL necesitamos un objeto de tipo “org.hibernate.Query”. Query es una interface, por lo que necesitamos una clase que la implemente para usarla.

Afortunadamente el objeto “org.hibernate.Session” que estamos usando (sesion) tiene un método que nos permite obtener un objeto de este tipo:

Query query = sesion.createQuery("Aquí ira nuestra consulta");


En el lugar que he indicado con la cadena “Aquí ira nuestra consulta” es donde colocaremos el HQL que estemos usando.

Estas consultas pueden ser básicamente de tres tipos:

  • Búsquedas de listas de resultados (este es el tipo de consulta que hemos estado haciendo hasta el momento)
  • Búsquedas de un objeto único
  • Actualizaciones de datos (actualizaciones o eliminaciones)

Cada una de estas operaciones la realizamos con un método específico de la interface Query:

query.list();          //Para las listas de resultados
query.uniqueResult();  //Para los objetos unicos
query.executeUpdate(); //Para las actualizaciones de datos


Nosotros usaremos el primer método (list()) en los siguientes ejemplos.

Bien, ahora si veamos el método.

Crear este método será muy sencillo. Básicamente lo que haremos es crear un nuevo método, colocar los dos métodos auxiliares que creamos anteriormente, obtener un objeto query, colocarle la consulta anterior, e invocar a su método list.

El método, para no hacer la explicación más aburrida, queda de esta forma:

private void obtenNombres()
{
        iniciaOperacion();

        Query query = sesion.createQuery("SELECT u.nombre FROM Usuario as u");

        List<String> listaResultados = query.list();

        for (int i = 0; i < listaResultados.size(); i++)
        {
            System.out.println("Nombre " + i + ": " + listaResultados.get(i));
        }

        terminaOperacion();    
}


Ahora, solo nos queda colocar la siguiente llamada en el método main:

new Main();


y esto en el constructor de Main:

obtenNombres();


La clase Main debe quedar así:

public class Main 
{
    private Session sesion;

    public Main()
    {
        obtenNombres();
    }

    public static void main(String[] args) 
    {
        new Main();
    }

    private void iniciaOperacion()
    {
        SessionFactory sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
        sesion = sessionFactory.openSession();
        sesion.getTransaction().begin();
    }

    private void terminaOperacion()
    {
        sesion.getTransaction().commit();
        sesion.close();
    }

    private void obtenNombres()
    {
        iniciaOperacion();

        Query query = sesion.createQuery("SELECT u.nombre FROM Usuario as u");

        List<String> listaResultados = query.list();

        for (int i = 0; i < listaResultados.size(); i++)
        {
            System.out.println("Nombre " + i + ": " + listaResultados.get(i));
        }

        terminaOperacion();
    }
}


Ahora, al ejecutar la aplicación vemos la siguiente salida:



Como vemos, obtuvimos solamente los nombres, justo como esperábamos ^-^.

La clausula SELECT también nos permite recuperar múltiples objetos y/o propiedades de objetos. Es este caso ocurre lo que expliqué anteriormente: recuperamos una lista de arreglos de objetos. Para comprobar esto, crearemos una consulta que recuperará el nombre y el password de un usuario.

Coloquemos la siguiente clausula en el ejecutor de HQL de NetBeans:

SELECT u.nombre, u.password FROM Usuario as u


Con lo que obtenemos la siguiente salida:



Como esta salida también es poco clara, crearemos un nuevo método para ver que, efectivamente, estemos recuperando una lista de arreglos de objetos con los valores indicados.

Como en este caso estamos recuperando dos valores (nombre y password), el primer elemento del arreglo (el elemento 0) será el nombre, y el segundo (el elemento 1) será el password:

private void obtenNombresYPasswords()
{
        iniciaOperacion();

        Query query = sesion.createQuery("SELECT u.nombre, u.password FROM Usuario as u ");

        List<Object[]> listaResultados = query.list();

        for (int i = 0; i < listaResultados.size(); i++)
        {
            System.out.println("Nombre " + i + ": " + listaResultados.get(i)[0] + ", password: " + listaResultados.get(i)[1]);
        }

        terminaOperacion();
}


Cuando ejecutamos este código obtenemos la siguiente salida:



Como vemos, al hacer

listaResultados.get(i)[0]


Obtenemos el nombre que se encuentra en el primer elemento del arreglo, y al hacer

listaResultados.get(i)[1]


Obtenemos el password que se encuentra en el segundo elemento del arreglo, justo como habíamos predicho ^-^.

Aunque esto que acabamos de ver nos resultará bastante útil cuando no necesitemos todo el objeto (ya que nos ahorrará mucha memoria) puede parecernos un poco raro trabajar con arreglos de objetos; más a los que estamos acostumbrados solo a las listas ( ^-^!).

Para personas como yo, Hibernate nos permite recuperar estos valores dentro de una lista, en vez del arreglo de objetos, usando una notación especial. A partir de aquí veremos algunas sintaxis extrañas, pero no se preocupen, que con el tiempo nos acostumbraremos a verlas.

Para recuperar los mismos datos que en el ejemplo anterior, pero con una lista en vez de un arreglo de objetos, debemos escribir la consulta de la siguiente forma:

SELECT new list(u.nombre, u.password) FROM Usuario as u


Como vemos la consulta es muy similar a la anterior, pero con ese extraño elemento “new list”. Coloquémonos en el NetBeans:



Como podemos ver el NetBeans tampoco nos ayuda mucho cuando trabajamos con este tipo de consultas u.u, así que tendremos que crear nuevamente un método:

private void obtenNombresYPasswordsComoLista()
{
    iniciaOperacion();

    Query query = sesion.createQuery("SELECT new list(u.nombre, u.password) FROM Usuario as u ");

    List<List> listaResultados = query.list();

    for (int i = 0; i < listaResultados.size(); i++)
    {
        System.out.println("Nombre " + i + ": " + listaResultados.get(i).get(0) + ", password: " + listaResultados.get(i).get(1));
    }

    terminaOperacion();
}


Con lo que obtenemos la siguiente salida:



Como podemos ver, obtuvimos el mismo resultado que en la ocasión anterior, pero ahora en vez de hacer esto:

listaResultados.get(i)[0] 
listaResultados.get(i)[1]


Hacemos esto:

listaResultados.get(i).get(0) 
listaResultados.get(i).get(1)


Podemos incluso recuperar un objeto propio pasando los valores a su constructor o recuperar un Map. Pero eso escapa al propósito de este tutorial.

Y como me he tardado más de lo esperado en escribir este tutorial, lo dejaré hasta aquí en este momento y lo terminaré en una segunda parte. Falta ver un poco de la sentencia WHERE, funciones de agregación, y sub-consultas, así que espero sea un poco más corto.

No olviden dejar todas sus dudas y comentarios. También pongan lo que les gustaría ver en el siguiente tutorial.

Saludos.

Entradas Relacionadas:

37 comentarios:

  1. Que tal Alex. Te doy las gracias por esforzarte y ayudarnos a todos los que nos iniciamos en hibernate! Eh bajado un monton de tutoriales pero ninguno tiene tu calidad y claridad. De verdad muchas Gracias! Lo que me gustaria ver mas adelante es si podes dar una pasadita en como usar Hibernmate junto con Spring ya que por lo que eh visto es muy interesante, pero todavia no tengo claro ciertas cosas! Eh logrado hacer andar un programa usando esta tecnologia con un par de relaciones medias complejas y la verdad que Spring simplifica bastante ciertas cosas y me gustaria mucho ver tu explicacion! Desde ya muchas gracias por todo. Saludos Eric Hidalgo

    ResponderEliminar
  2. Hola Eric;

    Muchas gracias por tus comentarios, hago lo mejor que puedo.

    Me gustaría pronto poder escribir un tutorial de Spring ya que me gusta mucho; y como dices simplifica mucho las cosas.

    Será cosa de que me haga un tiempo y lo escriba, tal vez terminando esta serie sobre Hibernate ^-^.

    Saludos

    ResponderEliminar
  3. Hola Amigo Gracias por tus tutoriales. Mi pregunta sale un poco del tema de HQl, lo que quiero saber es como creo reportes en ireport con hibernate.

    el ireport lo tengo como plugin en netbeans, mis clases son con anotaciones.

    lo que hago es agrego el jar de mi aplicacion al classpach de ireport. Al realizar un nuevo reporte y creo la coneccion con hibernate y al hacer el test obtengo como resultado que se realizo correctamente, pero para realizar mi consulta no carga ninguna de mis clases, y cuando escribo la consulta directa osea escribo "From com.MegaSoft.endrago.Clases.Clientes" esa es la direccion de mi clase, obtengo como resultado null. y no se como hacerlo, agradeceria mucho si me ayudaras con mi problema gracias.

    ResponderEliminar
  4. Hola Jorge;

    Muchas gracias por tus comentarios, hago lo que puedo para que se encientan lo mejor posible.

    Lamentablemente creo que no puedo ayudarte con tu pregunta ya que nunca he utilizado Hibernate junto con JasperReports como me parece que tu lo estas usando, así que no se que es lo que pueda estar ocurriendo.

    Trataré de hacer un ejemplo para darme una idea de cómo funcionan estas dos tecnologías juntas para ver si puedo ayudarte.

    Saludos

    ResponderEliminar
  5. Hola Alex, antes que nada felicitarte por el esfuerzo que le pones a tus tutoriales, son realmente estupendos sobre todo mostrar como se realizan los mapeos tanto usando anotaciones como archivos xml, seria interesante mostrar tambien como maneja la herencia hibernate.

    Un saludo

    ResponderEliminar
  6. Hola RHLeone;

    Si, creo que será lo siguiente que haga después de la segunda y última parte de este tutorial.

    Tal vez sea lo último que haga sobre Hibernate y después hare algo de Spring o de desarrollo web, aún no estoy seguro de que hare después.

    Saludos.

    ResponderEliminar
  7. excelentes tutoriales , espero pronto la segunda parte de HQL. gracias

    ResponderEliminar
  8. Hola Alex, te felicito por estos tutoriales, me han ayudado mucho para iniciarme en hibernate.

    Sabes donde puedo encontrar ejemplos o tutoriales sobre el manejo de hibernate con visual web pack(visual jsf).espero que me puedas ayudar.un saludo y gracias de nuevp

    ResponderEliminar
  9. Muy buen tutorial, es lo mejor de lo mejor que he encontrado y muchas mas importante en español ya que la mayoria este en ingles, por favor no dejes de hacer tutoriales y como te dije por correo revisa lo de iceface y si lo sabes comparte con nosotros tus conocimientos, quisiera q me hagas un gran favor sobre icefaces si pudieras hacerlo, en este tutorial http://facestutorials.icefaces.org/tutorial/autocomplete-tutorial.html para hacer el autocompletado, los datos lo saca de xml, quisiera saber como hacer para sacarlo de una lista o un vector que obtenemos de una base de datos, espero no abusar de tu confianza y muchas gracias de antemano por todo

    ResponderEliminar
  10. hola hola!!soy yo nuevamente, no tendras un ejemplo de como mapear y hacer consultas pero con herencia??

    ResponderEliminar
  11. Hola alex!!!!

    oye para que es la tabla usuarios_permisos??? yo pense que la relacion hiba a ser de usuario a permisos de muchos a muchos ya que vi la tabla usuarios_permisos pero comentas que la relacion entre usuarios y permisos es de uno a muchos unidireccional.

    ResponderEliminar
  12. Hola Juan Carlos;

    La tabla "usuarios_permisos" es necesaria en este tipo de relaciones ya que, tenemos que un "Usuario" puede tener varios "Permisos". O sea una relación "uno a muchos" entre Usuario y Permisos.

    Para que esta relación exista se deben realcionar los identificadores de los "Usuarios" y de los "Permisos", sin embargo esta relación no puede mostrarse ni en la tabla "usuarios" ni en la tabla "permisos", por eso se crea una tercera. Me explico:

    Un "Usuario" puede tener N "Permisos", por lo que si quisieras almacenarlos en la tabla "Usuarios" necesitarias n columas (permiso1, permiso2, permiso3, ... permisoN) una para cada "Permiso" que exista y colocas 1 si lo tiene y 0 si no (o algo por el estilo). Esta solución funcionaría pero es muy ineficiente. ¿Y qué ocurre si agregas un permiso nuevo? Tienes que agregar una nueva columna. ¿Y si lo quitamos? Por lo tanto podemos descartar esta opción.

    Por otro lado, tampoco puede guardarse la relación en la tabla "permisos", ya que el mismo "Permiso" puede pertenecer a varios "Empleados".

    Como no podemos almacenar esta relación en ninguna de estas dos tablas, necesitamos crear una tercera ("usuarios_permisos") que almacena los identificadores de los "Usuarios" relacionados con los identificadores de los "Permisos" que tienen.

    Espero que con esta explicación haya aclarado tu duda. Sino no dudes en seguir preguntando hasta que todo quede claro ^-^.

    Saludos

    ResponderEliminar
    Respuestas
    1. Hola Alex!!!

      Lo primero felicitarte por tu trabajo haciendo estos tutoriales, pues son de lo mejor que hay sobre el tema, lo siguiente que te quería comentar, es que creo que el amigo Juan Carlos tiene razón, de hecho en tu explicación queda más claro que es una relación muchos a muchos.

      Dices:
      " Usuario" puede tener N "Permisos" ".
      En el párrafo de abajo dices:
      "Por otro lado, tampoco puede guardarse la relación en la tabla "permisos", ya que el mismo "Permiso" puede pertenecer a varios "Empleados"" (Donde pones empleados supongo que quieres decir Usuario".

      Conclusión:
      Si un usuario puede tener muchos permisos y un permiso puede pertenecer a muchos usuarios esto quiere decir que es una relación Muchos a Muchos.

      Eliminar
  13. ha ya!!! sí sí ya entendi,

    bueno a como yo entiendo el problema y el analisis que hice es que las tablas usuarios, permisos y direcciones son de catalogos y la tabla de usuarios_permisos es la tabla que va a recibir la informacion de captura, de hecho hice un pequeño diagrama de clases de UML para representar el modelo e hice algunos cambios en la tabla usuarios_permisos ( le agregue un campo id por que yo lo mapee con un hbm)

    creo que aqui no puedo poner imagenes, no tienes correo de gmail para que te la envie??

    ResponderEliminar
  14. Alex!!! navegando encontre tu blog, el tutorial de hibernate es lo mas completo que vi en la web esta genial para aquellos que quieran persistir haciend xml o annotatios, gracias por compartir tu conocimiento y enseñar hibernate.saludos

    ResponderEliminar
  15. Che Alex!!! hace pronto el tutorial de spring con hibernate, que tambien es bastante interesantes aprender esa combinacion, saludos!!!

    ResponderEliminar
  16. Enhorabuena, me he estado intentando poner las pilas con hibernate y java, y he visto muchas web y tutoriales, pero como el tuyo ninguno. Muchas gracias.

    ResponderEliminar
  17. Hola a todos;

    Muchas gracias por sus comentarios, muy pronto comenzaré con la siguiente serie de tutoriales. Solo estoy deciciendo qué nuevo tema tocar. Estoy básicamente deciciendo entre Spring o pruebas de nuestro código.

    Saludos

    ResponderEliminar
  18. Muy buen tutotial amigo la vdd de lo mejor que e visto esta seccion no tien descarga la podrias poner

    ResponderEliminar
  19. Hola alex, en primer lugar le queria comentar que estos tutoriales me estan ayudando mucho y en segundo lugar le queria preguntar si las clases que estan en el paquete dominio es igual a las clases javabeans del paquete llamado normalmente dominio de cualquier aplicacion web. Ya sé que esta pregunta será muy basica pero soy novata en esto. Un saludo

    ResponderEliminar
  20. @Teresa
    Hola Teresa; que bueno que los tutoriales te estan ayudando, me da mucho gusto :D. sobre tu pregunta, pues en realidad la respuesta debe ser un "depende". En realidad no hay como una convención estandar de los paquetes que debe tener una aplicación, cada empresa o cada persona tendrá su propia convención. En este caso el dominio se puede referir al dominio de negocio. Aunue, como te digo, esto depende de la convención de cada uno. Yo por lo general estas clases las coloco en un paquete llamado "negocio", pero será cosa de que generes tu propia convención de en qué paquete van cuales clases.

    Espero haber resuelto tu duda :)

    Saludos.

    ResponderEliminar
  21. Hola alex,en primer lugar le queria comentar que me ayudo bastante su respuesta y en segundo lugar le queria comentar como puedo utilizar la estrategia de herencia que más me conviene con la ingenieria inversa de hibernate,no me genera el pojo correctamente. Espero que me pueda ayudar.

    ResponderEliminar
  22. hola alex, esta muy bueno tu tutorial..

    una pregunta, me fije que cuando estabas haciendo las consultas, con el editor hql de netbeans, no te retorna el valor de las claves foreanes sino una referencia..

    por ejemplo, cuando haces from usuarios te retorna todos los valores asociados a esa tabla y si te fijas los que son claves foraneas no te trae el valor sino como una referencia..

    como se haria para obtener dicho valor y no la referencia?

    gracias de antemano

    saludos

    ResponderEliminar
  23. jaaaaaaaaa que grande Alex..!!! epetaculaaa :D:D

    ResponderEliminar
  24. seria bueno los archivos de descarga ya q estoy trabajando con las mapeos hbm y aqui solo tienes las anotaciones

    ResponderEliminar
  25. Yo quisiera ver si me peude ayudar coneste error, que me va pasando hace unos cuantos dias y no se como solucionarlo gracias

    Exception in thread "main" java.lang.NoClassDefFoundError: javax/persistence/Cacheable
    at org.hibernate.cfg.AnnotationBinder.determineCacheSettings(AnnotationBinder.java:988)
    at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:579)
    at org.hibernate.cfg.Configuration$MetadataSourceQueue.processAnnotatedClassesQueue(Configuration.java:4008)
    at org.hibernate.cfg.Configuration$MetadataSourceQueue.processMetadata(Configuration.java:3962)
    at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1371)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1829)
    at hql.Main.iniciaOperacion(Main.java:54)
    at hql.Main.obtenNombres(Main.java:67)
    at hql.Main.(Main.java:37)
    at hql.Main.main(Main.java:49)
    Caused by: java.lang.ClassNotFoundException: javax.persistence.Cacheable
    at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:248)

    ResponderEliminar
  26. huyyyyyyyy siiii Spring seria bueno. no tengo muy claro como trabaja pero segun lo que he leido de cosas como inyeccion de dependencias y algo que he escuchado.
    Te agradeceria mil si te dieras el tiempo de realizar un tutorial tan bueno como estos de hibernate que hasta ahora le voy pillando de maravilla, gracias y Saludos!!

    ResponderEliminar
  27. @gnu.cubo
    Hola Cubo ^_^

    Puedes encontrar un tutorial de Spring aqui:

    http://www.javatutoriales.com/2010/09/spring-parte-1-introduccion.html

    Saludos :D

    ResponderEliminar
  28. Hola que tal gracias por todo tu aporte, es de mucha ayuda para todos nosotros que iniciamos en este mundo de hibernate, una pregunta que consulta debo hacer para recuperar en esta relacion de este ejemplo: relación uno a muchos de "Usuario" con "Permiso", quisiera recuperar todos los permisos sin repetir de Usuario, no se si me esplico, en otras palabras quiero saber cuales permisos estan siendo utilizados por los usuario

    ResponderEliminar
  29. muy bueno te felicito sigue adelante con la ayuda de Dios

    ResponderEliminar
  30. Excelente,

    Me gustaría saber si tienes algo para acceder rápidamente a una lista ó quizás se puede usar otra cosa para la colección, yo entiendo que en un arrayList tiene indice pero como se cúal es el indice de un objeto de 10 campos por ejemplo, según la doc hay que pasarle el objeto completo para saber obtener el indice, cuando en realidad en mi caso solo tengo el resultado del primer campo no el objeto completo(10 campos)....
    como busco ese objeto de la lista si tengo solo un campo para buscarlo, lo hago actualmente con un foreach pero me gustaría saber si hay otra forma más rápida....


    ** otra consulta esta misma colección de 10 campos como dejo uno de ellos como key para usar un hashmap ó map no tengo claro cúal ahora pero esa es la idea....

    ojalá me puedas entender thanks...

    saludos y felicitaciones

    ResponderEliminar
  31. Hola Alex.

    Primero que todo, agradecerte por el estupendo material que publicas, de verdad que nos ha servidor mucho.

    Tengo una inquietud, yo estoy trabajando con una BD PostgreSQL, y no me ha funcionado la parte de HQL, cuando digito from Usuario, me aparece lo siguiente (cabe anotar que el archivo hibernate.cfg.xml y las clases están tal cual las definiste en el tutorial):

    org.hibernate.hql.ast.QuerySyntaxException: Usuario is not mapped [from Usuario]
    at org.hibernate.hql.ast.util.SessionFactoryHelper.requireClassPersister(SessionFactoryHelper.java:158)
    at org.hibernate.hql.ast.tree.FromElementFactory.addFromElement(FromElementFactory.java:87)
    at org.hibernate.hql.ast.tree.FromClause.addFromElement(FromClause.java:70)
    at org.hibernate.hql.ast.HqlSqlWalker.createFromElement(HqlSqlWalker.java:255)
    at org.hibernate.hql.antlr.HqlSqlBaseWalker.fromElement(HqlSqlBaseWalker.java:3056)
    at org.hibernate.hql.antlr.HqlSqlBaseWalker.fromElementList(HqlSqlBaseWalker.java:2945)
    at org.hibernate.hql.antlr.HqlSqlBaseWalker.fromClause(HqlSqlBaseWalker.java:688)
    at org.hibernate.hql.antlr.HqlSqlBaseWalker.query(HqlSqlBaseWalker.java:544)
    at org.hibernate.hql.antlr.HqlSqlBaseWalker.selectStatement(HqlSqlBaseWalker.java:281)
    at org.hibernate.hql.antlr.HqlSqlBaseWalker.statement(HqlSqlBaseWalker.java:229)
    at org.hibernate.hql.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:228)
    at org.hibernate.hql.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:160)
    at org.hibernate.hql.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:111)
    at org.hibernate.engine.query.HQLQueryPlan.(HQLQueryPlan.java:77)
    at org.hibernate.engine.query.HQLQueryPlan.(HQLQueryPlan.java:56)
    at org.hibernate.engine.query.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:72)
    at org.hibernate.impl.AbstractSessionImpl.getHQLQueryPlan(AbstractSessionImpl.java:133)
    at org.hibernate.impl.AbstractSessionImpl.createQuery(AbstractSessionImpl.java:112)
    at org.hibernate.impl.SessionImpl.createQuery(SessionImpl.java:1623)


    Muchas gracias por la ayuda de quien pueda responderme.


    ResponderEliminar
    Respuestas
    1. Tengo el mismo problema, si alguien lo ha resuelto se agradece la respuesta

      Eliminar
  32. Podrías ayudarme a poner en un tabla en un jsp los resultados de estas consultas.
    Gracias

    ResponderEliminar
  33. gracias por el blog me fue de mucha ayuda

    ResponderEliminar
  34. Hola Alex mi enhorabuena por estos tutoriales.
    queria comentarte que respecto a las consultas HQL, al introducir el FROM hql.modelo.Usuario
    no me aparece ningún resultado, he revisado todo tal y como tu lo tienes.
    No se que se me escapa :(
    no hay ningún error en las clases
    por que puede ser?
    muchas gracias!

    ResponderEliminar
  35. Hola una pregunta si quiero operar datos numericos como se realizaria una conversion a entero....puede ser algo asi (int) (listSumHuespedes.get(i).get(1)

    ResponderEliminar