java - español - ¿Qué tipo de objeto devuelve el método Spring Hibernate Template para una consulta de recuento en Oracle?
hibernate tutorial español (4)
Cuando se ejecuta contra y la base de datos Oracle, ¿cuál es el tipo de tiempo de ejecución del objeto que devuelve el siguiente código Spring Hibernate Template (Spring 2.5 e Hibernate 3.3.2GA) donde la consulta SQL es una consulta de conteo como select count(*) from table
?
String sql = "select count(*) from table";
BigDecimal count = (BigDecimal) hibernateTemplate.execute(
new HibernateCallback() {
public Object doInHibernate(Session session) throws HibernateException {
SQLQuery query = session.createSQLQuery(sql);
return (BigDecimal) query.uniqueResult();
}});
return count;
Este código arroja la siguiente excepción:
javax.ejb.EJBException: EJB Exception: : java.lang.ClassCastException: java.math.BigDecimal cannot be cast to [Ljava.lang.Object;
at org.hibernate.cache.StandardQueryCache.put(StandardQueryCache.java:83)
at org.hibernate.loader.Loader.putResultInQueryCache(Loader.java:2185)
at org.hibernate.loader.Loader.listUsingQueryCache(Loader.java:2129)
at org.hibernate.loader.Loader.list(Loader.java:2087)
at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:289)
at org.hibernate.impl.SessionImpl.listCustomQuery(SessionImpl.java:1695)
at org.hibernate.impl.AbstractSessionImpl.list(AbstractSessionImpl.java:142)
at org.hibernate.impl.SQLQueryImpl.list(SQLQueryImpl.java:150)
at org.hibernate.impl.AbstractQueryImpl.uniqueResult(AbstractQueryImpl.java:804)
at com.db.abstrack.dao.hibernate.RfqCdoUsDaoHibernate$1.doInHibernate(RfqCdoUsDaoHibernate.java:124)
Creo que devuelve tipo Long. He usado Long en mi código. Pero si su BigDecimal funciona, incluso yo quiero saber cuál es el tipo de devolución :)
Qué tal si
long value = ((Number)query.uniqueResult()).longValue();
return Long.valueOf(value);
Esto funcionaría para todas las subclases de Number como Long, Double, Biginteger o BigDecimal.
El tipo de clase del objeto que hibernateTemplate.execute()
devuelve es de hecho BigDecimal
. Resulta que la causa de ClassCastException
es el molde del valor de retorno del método doInHibernate()
:
(BigDecimal) query.uniqueResult();
Código corregido:
BigDecimal count = (BigDecimal) hibernateTemplate.execute(
new HibernateCallback() {
public Object doInHibernate(Session session) throws HibernateException {
SQLQuery query = session.createSQLQuery(sql);
return query.uniqueResult();
}});
return count;
Resulta que ClassCastException
puede deberse a un error en el caché de consultas estándar de Hibernate.
La solución es agregar un escalar a la consulta:
String sql = "select count(*) as result from table";
BigDecimal count = (BigDecimal) ht.execute(new HibernateCallback() {
public Object doInHibernate(Session session)
throws HibernateException {
SQLQuery query = session.createSQLQuery(sql);
// Add scalar to avoid bug in Hibernate query cache.
query.addScalar("result", Hibernate.BIG_DECIMAL);
return query.uniqueResult();
}
});
Referencias
- ClassCastException con SQLQuery y setCacheable (true)
- Blog de Martin Schaaf: ClassCastException con SQLQuery y setCacheable (true)
- Almacenamiento en caché de un recuento de sql sin procesar con Hibernate y EhCache
- HHH-5163 Error al aplicar un ResultTransformer en un criterio basado en una proyección cacheable
- ClassCastException cuando Hibernate intenta almacenar en caché los resultados utilizando ResultTransformer