Diferencia entre revisiones de «Consultas Con HibernateTemplate»
(→Buscando colecciones con HQL) |
(→Buscar un objeto por ID) |
||
(No se muestran 16 ediciones intermedias de 5 usuarios) | |||
Línea 1: | Línea 1: | ||
− | Los | + | [[Category:Spring Framework]] |
+ | [[Category:Hibernate]] | ||
+ | En [[Spring Framework]], Los DAO que heredan de ''HibernateDaoSupport'' tienen acceso al método ''getHibernateTemplate'', el cual devuelve una clase con diversas utilidades para manejar objetos con Hibernate. | ||
===Buscar un objeto por ID=== | ===Buscar un objeto por ID=== | ||
Línea 6: | Línea 8: | ||
''load()'' de la Session de Hibernate. | ''load()'' de la Session de Hibernate. | ||
− | ''get()'' busca una entidad por su PK, y | + | ''get()'' busca una entidad por su PK, y tira una DataAccessException si no lo encuentra. Por otro lado, ''load()'' realiza la misma operación, pero devuelve null si no la encuentra. En general, debe usarse ''load()'' cuando no se espera que la entidad no se encuentre. |
+ | <code java> | ||
public Invasor buscarInvasorPorId(Long id) { | public Invasor buscarInvasorPorId(Long id) { | ||
return getHibernateTemplate().get(Invasor.class, id); | return getHibernateTemplate().get(Invasor.class, id); | ||
} | } | ||
+ | </code> | ||
===Buscar colecciones con Criteria=== | ===Buscar colecciones con Criteria=== | ||
Línea 20: | Línea 24: | ||
Suponiendo que un Invasor tenga un Estado (relación muchos-a-uno desde el Invasor al Estado), se puede referenciar directamente al Estado de un Invasor (como si fuera un atributo más... que de hecho, lo es!). | Suponiendo que un Invasor tenga un Estado (relación muchos-a-uno desde el Invasor al Estado), se puede referenciar directamente al Estado de un Invasor (como si fuera un atributo más... que de hecho, lo es!). | ||
+ | <code java> | ||
public Collection<Invasor> buscarInvasoresPorEstado(Long idEstado) { | public Collection<Invasor> buscarInvasoresPorEstado(Long idEstado) { | ||
DetachedCriteria criteria = DetachedCriteria.forClass(Invasor.class); | DetachedCriteria criteria = DetachedCriteria.forClass(Invasor.class); | ||
Línea 25: | Línea 30: | ||
return getHibernateTemplate().findByCriteria(criteria); | return getHibernateTemplate().findByCriteria(criteria); | ||
} | } | ||
− | + | </code> | |
La clase Restrictions tiene varios operadores útiles, como ser LIKE case-unsensitive. Además, se pueden establecer criterios de ordenamiento. | La clase Restrictions tiene varios operadores útiles, como ser LIKE case-unsensitive. Además, se pueden establecer criterios de ordenamiento. | ||
+ | <code java> | ||
public Collection<Invasor> buscarInvasoresPorEstadoNombre(Long idEstado, String nombre) { | public Collection<Invasor> buscarInvasoresPorEstadoNombre(Long idEstado, String nombre) { | ||
Línea 37: | Línea 43: | ||
return getHibernateTemplate().findByCriteria(criteria); | return getHibernateTemplate().findByCriteria(criteria); | ||
} | } | ||
+ | </code> | ||
===Buscar colecciones con HQL=== | ===Buscar colecciones con HQL=== | ||
En ciertas circunstancias, puede ser preferible usar HQL. HibernateTemplate también provee algunos métodos útiles para esto. Supongamos el mismo método ''buscarInvasoresPorEstado()'', esta vez resuelto con HQL. | En ciertas circunstancias, puede ser preferible usar HQL. HibernateTemplate también provee algunos métodos útiles para esto. Supongamos el mismo método ''buscarInvasoresPorEstado()'', esta vez resuelto con HQL. | ||
− | < | + | <code java> |
private final String QUERY = "from Invasor invasor where invasor.estado.id = ?"; | private final String QUERY = "from Invasor invasor where invasor.estado.id = ?"; | ||
Línea 47: | Línea 54: | ||
return getHibernateTemplate().find(QUERY, idEstado); | return getHibernateTemplate().find(QUERY, idEstado); | ||
} | } | ||
− | </ | + | </code> |
+ | |||
+ | Otra alternativa es utilizar el método ''iterate()'' que devuelve un iterador para recorrer los resultados. | ||
+ | |||
+ | <code java> | ||
+ | private final String QUERY = "from Invasor invasor where invasor.estado.id = ?"; | ||
+ | |||
+ | public Iterator<Invasor> buscarIteradorDeInvasoresPorEstado(Long idEstado) { | ||
+ | HibernateTemplate ht = getHibernateTemplate(); | ||
+ | ht.setFetchSize(15); | ||
+ | Iterator it = ht.iterate(QUERY, idEstado); | ||
+ | return it; | ||
+ | } | ||
+ | </code> | ||
− | === | + | Importante: Notar que con esta alternativa, se modifica el fetch size del template de hibernate incluso para las siguientes utilizaciones del dao. Para utilizar el default, debería volver a setearse en 0. |
+ | |||
+ | Un análisis de estas alternativas se puede ver en [[Eficiencia Ejecutando Querys Con Hibernate]] | ||
+ | |||
+ | ===Buscar colecciones por muestra=== | ||
A veces puede ser útil realizar una búsqueda por "muestra". En estas búsquedas, se crea un objeto mapeado seteando los valores que queremos ubicar, y este mismo objeto es usado como filtro para crear la consulta. En este tipo de búsquedas no se tiene en cuenta el ID del objeto de muestra (es decir, aunque el objeto de muestra tenga seteado su PK, no será utilizada para la búsqueda). | A veces puede ser útil realizar una búsqueda por "muestra". En estas búsquedas, se crea un objeto mapeado seteando los valores que queremos ubicar, y este mismo objeto es usado como filtro para crear la consulta. En este tipo de búsquedas no se tiene en cuenta el ID del objeto de muestra (es decir, aunque el objeto de muestra tenga seteado su PK, no será utilizada para la búsqueda). | ||
+ | <code java> | ||
public Collection<Invasor> buscarInvasoresPorFechaEnrolamiento(Date fechaEnrolamiento) { | public Collection<Invasor> buscarInvasoresPorFechaEnrolamiento(Date fechaEnrolamiento) { | ||
Invasor invasor = new Invasor(); | Invasor invasor = new Invasor(); | ||
Línea 57: | Línea 82: | ||
return getHibernateTemplate().findByExample(invasor); | return getHibernateTemplate().findByExample(invasor); | ||
} | } | ||
+ | </code> | ||
− | + | ===Buscar un sólo objeto con consultas=== | |
− | === | ||
Los métodos find (de Criteria o HQL) siempre devuelve colecciones de objetos. Pero, ¿qué pasa si sabemos que nuestro query sólo puede devolver una instancia? Para esto, podemos usar la clase ''DataAccessUtils'' de Spring. | Los métodos find (de Criteria o HQL) siempre devuelve colecciones de objetos. Pero, ¿qué pasa si sabemos que nuestro query sólo puede devolver una instancia? Para esto, podemos usar la clase ''DataAccessUtils'' de Spring. | ||
Línea 65: | Línea 90: | ||
Como todos saben, cada comandante de la flota Irken sólo puede liderar una nave espacial (son petisos los Irken, no les daría para ir paseando por diversas naves...) | Como todos saben, cada comandante de la flota Irken sólo puede liderar una nave espacial (son petisos los Irken, no les daría para ir paseando por diversas naves...) | ||
+ | <code java> | ||
public NaveEspacial buscarNaveEspacialPorComandante(Long idInvasor) { | public NaveEspacial buscarNaveEspacialPorComandante(Long idInvasor) { | ||
DetachedCriteria criteria = DetachedCriteria.forClass(NaveEspecial.class); | DetachedCriteria criteria = DetachedCriteria.forClass(NaveEspecial.class); | ||
criteria.add(Restrictions.eq("idInvasorComandate", idInvasor)); | criteria.add(Restrictions.eq("idInvasorComandate", idInvasor)); | ||
return (NaveEspacial) DataAccessUtils.uniqueResult(getHibernateTemplate().findByCriteria(criteria)); | return (NaveEspacial) DataAccessUtils.uniqueResult(getHibernateTemplate().findByCriteria(criteria)); | ||
+ | //jaime | ||
} | } | ||
+ | </code> | ||
El método ''DataAccessUtils.uniqueResult()'' lanzará una excepción si la consulta devuelve más de un resultado. | El método ''DataAccessUtils.uniqueResult()'' lanzará una excepción si la consulta devuelve más de un resultado. | ||
− | + | ===Paginar resultados=== | |
− | === | ||
Los métodos de búsqueda tienen una forma simple para paginar resultados. El método ''findByCriteria(criteria, desde, cantidad)'' permite obtener un set reducido de datos. | Los métodos de búsqueda tienen una forma simple para paginar resultados. El método ''findByCriteria(criteria, desde, cantidad)'' permite obtener un set reducido de datos. | ||
Línea 80: | Línea 107: | ||
El siguiente método devuelve el "Top ten" de los mejores Invasores de la flota. | El siguiente método devuelve el "Top ten" de los mejores Invasores de la flota. | ||
+ | <code java> | ||
public Collection<Invasor> buscarMejoresInvasores() { | public Collection<Invasor> buscarMejoresInvasores() { | ||
DetachedCriteria criteria = DetachedCriteria.forClass(Invasor.class); | DetachedCriteria criteria = DetachedCriteria.forClass(Invasor.class); | ||
Línea 85: | Línea 113: | ||
return getHibernateTemplate().findByCriteria(criteria,0,10); | return getHibernateTemplate().findByCriteria(criteria,0,10); | ||
} | } | ||
+ | </code> | ||
==Ver también== | ==Ver también== | ||
− | * | + | * [[Hibernate Con Spring]] |
Revisión actual del 17:35 18 jul 2011
En Spring Framework, Los DAO que heredan de HibernateDaoSupport tienen acceso al método getHibernateTemplate, el cual devuelve una clase con diversas utilidades para manejar objetos con Hibernate.
Contenido
Buscar un objeto por ID
Si necesitamos buscar un objeto por su ID, tenemos básicamente dos opciones: usar el método get() o el método load() de la Session de Hibernate.
get() busca una entidad por su PK, y tira una DataAccessException si no lo encuentra. Por otro lado, load() realiza la misma operación, pero devuelve null si no la encuentra. En general, debe usarse load() cuando no se espera que la entidad no se encuentre.
public Invasor buscarInvasorPorId(Long id) { return getHibernateTemplate().get(Invasor.class, id); }
Buscar colecciones con Criteria
Existen dos formas básicas de realizar estas consultas: utilizando Criteria, o escribiendo la consulta en HQL.
Generalmente, utilizar Criteria es más simple y facil de programar, y suele ser una buena elección cuando en la consulta se realiza sobre el objeto mapeado (y las relaciones que tenga explicitamente mapeadas). En otros casos, el query en HQL puede ser más conveniente.
Suponiendo que un Invasor tenga un Estado (relación muchos-a-uno desde el Invasor al Estado), se puede referenciar directamente al Estado de un Invasor (como si fuera un atributo más... que de hecho, lo es!).
public Collection<Invasor> buscarInvasoresPorEstado(Long idEstado) { DetachedCriteria criteria = DetachedCriteria.forClass(Invasor.class); criteria.add(Restrictions.eq("estado.id", idEstado)); return getHibernateTemplate().findByCriteria(criteria); }
La clase Restrictions tiene varios operadores útiles, como ser LIKE case-unsensitive. Además, se pueden establecer criterios de ordenamiento.
public Collection<Invasor> buscarInvasoresPorEstadoNombre(Long idEstado, String nombre) {
DetachedCriteria criteria = DetachedCriteria.forClass(Invasor.class); criteria.add(Restrictions.eq("estado.id", idEstado)); criteria.add(Restrictions.ilike("nombre", nombre)); criteria.addOrder(Order.desc("fechaEnrolamiento")); return getHibernateTemplate().findByCriteria(criteria); }
Buscar colecciones con HQL
En ciertas circunstancias, puede ser preferible usar HQL. HibernateTemplate también provee algunos métodos útiles para esto. Supongamos el mismo método buscarInvasoresPorEstado(), esta vez resuelto con HQL.
private final String QUERY = "from Invasor invasor where invasor.estado.id = ?";
public Collection<Invasor> buscarInvasoresPorEstado(Long idEstado) { return getHibernateTemplate().find(QUERY, idEstado); }
Otra alternativa es utilizar el método iterate() que devuelve un iterador para recorrer los resultados.
private final String QUERY = "from Invasor invasor where invasor.estado.id = ?";
public Iterator<Invasor> buscarIteradorDeInvasoresPorEstado(Long idEstado) { HibernateTemplate ht = getHibernateTemplate(); ht.setFetchSize(15); Iterator it = ht.iterate(QUERY, idEstado); return it; }
Importante: Notar que con esta alternativa, se modifica el fetch size del template de hibernate incluso para las siguientes utilizaciones del dao. Para utilizar el default, debería volver a setearse en 0.
Un análisis de estas alternativas se puede ver en Eficiencia Ejecutando Querys Con Hibernate
Buscar colecciones por muestra
A veces puede ser útil realizar una búsqueda por "muestra". En estas búsquedas, se crea un objeto mapeado seteando los valores que queremos ubicar, y este mismo objeto es usado como filtro para crear la consulta. En este tipo de búsquedas no se tiene en cuenta el ID del objeto de muestra (es decir, aunque el objeto de muestra tenga seteado su PK, no será utilizada para la búsqueda).
public Collection<Invasor> buscarInvasoresPorFechaEnrolamiento(Date fechaEnrolamiento) { Invasor invasor = new Invasor(); invasor.setFechaEnrolamiento(fechaEnrolamiento); return getHibernateTemplate().findByExample(invasor); }
Buscar un sólo objeto con consultas
Los métodos find (de Criteria o HQL) siempre devuelve colecciones de objetos. Pero, ¿qué pasa si sabemos que nuestro query sólo puede devolver una instancia? Para esto, podemos usar la clase DataAccessUtils de Spring.
Como todos saben, cada comandante de la flota Irken sólo puede liderar una nave espacial (son petisos los Irken, no les daría para ir paseando por diversas naves...)
public NaveEspacial buscarNaveEspacialPorComandante(Long idInvasor) { DetachedCriteria criteria = DetachedCriteria.forClass(NaveEspecial.class); criteria.add(Restrictions.eq("idInvasorComandate", idInvasor)); return (NaveEspacial) DataAccessUtils.uniqueResult(getHibernateTemplate().findByCriteria(criteria));
//jaime
}
El método DataAccessUtils.uniqueResult() lanzará una excepción si la consulta devuelve más de un resultado.
Paginar resultados
Los métodos de búsqueda tienen una forma simple para paginar resultados. El método findByCriteria(criteria, desde, cantidad) permite obtener un set reducido de datos.
El siguiente método devuelve el "Top ten" de los mejores Invasores de la flota.
public Collection<Invasor> buscarMejoresInvasores() { DetachedCriteria criteria = DetachedCriteria.forClass(Invasor.class); criteria.addOrder(Order.desc("cantPlanetasConquistados")); return getHibernateTemplate().findByCriteria(criteria,0,10); }