select count hibernate
CÓMO usar TENER COUNT(*) con Hibernate (4)
Necesito crear una consulta y necesito COUNT(*)
y HAVING COUNT(*) = x
.
Estoy usando una CustomProjection
que usa la clase CustomProjection
, que descargué en algún lugar.
Este es el SQL que trato de lograr:
select count(*) as y0_, this_.ensayo_id as y1_ from Repeticiones this_
inner join Lineas linea1_ on this_.linea_id=linea1_.id
where this_.pesoKGHA>0.0 and this_.nroRepeticion=1 and linea1_.id in (18,24)
group by this_.ensayo_id
having count(*) = 2
Este es el código, donde utilizo la clase Projection
Hibernate:
critRepeticion.setProjection(Projections.projectionList()
.add( Projections.groupProperty("ensayo") )
.add( CustomProjections.groupByHaving("ensayo_id",Hibernate.LONG,"COUNT(ensayo_id) = "+String.valueOf(lineas.size()))
.add( Projections.rowCount() )
);
El error es:
!STACK 0
java.lang.NullPointerException
at org.hibernate.criterion.ProjectionList.toSqlString(ProjectionList.java:50)
at org.hibernate.loader.criteria.CriteriaQueryTranslator.getSelect(CriteriaQueryTranslator.java:310)
at org.hibernate.loader.criteria.CriteriaJoinWalker.<init>(CriteriaJoinWalker.java:71)
at org.hibernate.loader.criteria.CriteriaLoader.<init>(CriteriaLoader.java:67)
at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1550)
at org.hibernate.impl.CriteriaImpl.list(CriteriaImpl.java:283)
at ar.com.cse.cseagro.controller.RepeticionController.buscarEnsayo(RepeticionController.java:101)
Si comento la línea con la clase CustomProjections
, la consulta funciona, pero no obtengo el filtro HAVING COUNT(*)
en el SQL ...
Básicamente, la consulta intenta recuperar, en un esquema maestro - detalle, todos los registros maestros donde una lista de detalles está presente simultáneamente, como si usted quisiera saber "qué facturas tienen ambos productos, A y B".
Por eso, si obtuve 3 elementos en la cláusula IN
, necesito usar la cláusula HAVING COUNT = 3
.
Alguna idea o sugerencia? Atentamente,
Resolví el problema. Sustituyo la clase CusotmProjections con:
.add( Projections.sqlGroupProjection("ensayo_id", groupBy , alias, types));
donde groupBy, alias y tipos son:
String groupBy = "ensayo_id" + " having " + "count(*) = " + String.valueOf(lineas.size());
String[] alias = new String[1];
Alias[0] = "ensayo_id";
Type[] types = new Type[1];
types[0] = Hibernate.INTEGER;
y la magia está en groupby String. -
Si alguien necesita hacerlo en grial sería como:
projections {
groupProperty("id")
sqlGroupProjection(...)
rowCount()
}
Donde sqlGroupProjection está disponible desde 2.2.0
/**
* Adds a sql projection to the criteria
*
* @param sql SQL projecting
* @param groupBy group by clause
* @param columnAliases List of column aliases for the projected values
* @param types List of types for the projected values
*/
protected void sqlGroupProjection(String sql, String groupBy, List<String> columnAliases, List<Type> types) {
projectionList.add(Projections.sqlGroupProjection(sql, groupBy, columnAliases.toArray(new String[columnAliases.size()]), types.toArray(new Type[types.size()])));
}
criteria.add (Restrictions.sqlRestriction ("1 = 1 que tiene count (*) = 2"));
Aquí está mi muestra, funciona bien, tal vez sea útil:
Mi consulta sql:
seleccione COLUMN1, suma (COLUMN2) del grupo MY_TABLE por COLUMN1 con suma (COLUMN2)> 1000;
Y Criteria sería:
Criteria criteria = getCurrentSession().createCriteria(MyTable.Class);
ProjectionList projectionList = Projections.projectionList();
projectionList.add(Projections.property("column1"), "column1");
projectionList.add(Projections.sqlGroupProjection("sum(column2) sumColumn2 ", "COLUMN1 having sum(COLUMN2) > 1000" , new String[]{"sumColumn2"}, new org.hibernate.type.Type[]{StandardBasicTypes.STRING}));
criteria.setProjection(projectionList);
criteria.List();