Ho risolto questo problema nella versione java (Hibernate). Il problema è che la funzione RowProjection è un po 'come:
count(*)
Quella è una funzione di aggregazione: quindi se si crea un 'gruppo da' immobile il risultato è una lista della riga raggruppata e per ogni riga si ha la conteggio totale del gruppo.
Per me, con database Oracle, per farlo funzionare ho creare una proiezione personalizzata che, invece di creare funzione count (*), la funzione è
count(count(*))
e la proprietà del gruppo da la clausola non viene scritta nella selezione ... dall'istruzione.Per fare che non è così semplice, il problema è che è necessario fornire tutte pila per creare lo sql destra in modo, con la versione Java ho a subclasse 2 classe: SimpleProjection ProjectionList
Dopo di che la mia domanda ha generato come:
select count(*), col1, col2 from table1 group by col1, col2
diventano
select count(count(*)) from table1 group by col1, col2
e il risultato sono riga totale in
select col1, col2 from table1 group by col1, col2
(utilizzabile con il sistema di impaginazione)
vi posto qui la versione Java delle classi, se sono utili per voi:
public class CustomProjectionList extends ProjectionList {
private static final long serialVersionUID = 5762155180392132152L;
@Override
public ProjectionList create() {
return new CustomProjectionList();
}
public static ProjectionList getNewCustomProjectionList() {
return new CustomProjectionList();
}
@Override
public String toSqlString(Criteria criteria, int loc, CriteriaQuery criteriaQuery) throws HibernateException {
StringBuffer buf = new StringBuffer();
for (int i = 0; i < getLength(); i++) {
Projection proj = getProjection(i);
String sqlString = proj.toSqlString(criteria, loc, criteriaQuery);
buf.append(sqlString);
loc += getColumnAliases(loc, criteria, criteriaQuery, proj).length;
if (i < (getLength() - 1) && sqlString != null && sqlString.length() > 0)
buf.append(", ");
}
return buf.toString();
}
private static String[] getColumnAliases(int loc, Criteria criteria, CriteriaQuery criteriaQuery, Projection projection) {
return projection instanceof EnhancedProjection ?
((EnhancedProjection) projection).getColumnAliases(loc, criteria, criteriaQuery) :
projection.getColumnAliases(loc);
}
}
public class CustomPropertyProjection extends SimpleProjection {
private static final long serialVersionUID = -5206671448535977079L;
private String propertyName;
private boolean grouped;
@Override
public String[] getColumnAliases(int loc, Criteria criteria, CriteriaQuery criteriaQuery) {
return new String[0];
}
@Override
public String[] getColumnAliases(int loc) {
return new String[0];
}
@Override
public int getColumnCount(Criteria criteria, CriteriaQuery criteriaQuery) {
return 0;
}
@Override
public String[] getAliases() {
return new String[0];
}
public CustomPropertyProjection(String prop, boolean grouped) {
this.propertyName = prop;
this.grouped = grouped;
}
protected CustomPropertyProjection(String prop) {
this(prop, false);
}
public String getPropertyName() {
return propertyName;
}
public String toString() {
return propertyName;
}
public Type[] getTypes(Criteria criteria, CriteriaQuery criteriaQuery)
throws HibernateException {
return new Type[0];
}
public String toSqlString(Criteria criteria, int position, CriteriaQuery criteriaQuery)
throws HibernateException {
return "";
}
public boolean isGrouped() {
return grouped;
}
public String toGroupSqlString(Criteria criteria, CriteriaQuery criteriaQuery)
throws HibernateException {
if (!grouped) {
return super.toGroupSqlString(criteria, criteriaQuery);
}
else {
return StringHelper.join(", ", criteriaQuery.getColumns(propertyName, criteria));
}
}
}
public class CustomRowCountProjection extends SimpleProjection {
/**
*
*/
private static final long serialVersionUID = -7886296860233977609L;
@SuppressWarnings("rawtypes")
private static List ARGS = java.util.Collections.singletonList("*");
public CustomRowCountProjection() {
super();
}
public String toString() {
return "count(count(*))";
}
public Type[] getTypes(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
return new Type[] {
getFunction(criteriaQuery).getReturnType(null, criteriaQuery.getFactory())
};
}
public String toSqlString(Criteria criteria, int position, CriteriaQuery criteriaQuery) throws HibernateException {
SQLFunction countSql = getFunction(criteriaQuery);
String sqlString = countSql.toString() + "(" + countSql.render(null, ARGS, criteriaQuery.getFactory()) + ") as y" + position + '_';
return sqlString;
}
protected SQLFunction getFunction(CriteriaQuery criteriaQuery) {
SQLFunction function = criteriaQuery.getFactory()
.getSqlFunctionRegistry()
.findSQLFunction("count");
if (function == null) {
throw new HibernateException("Unable to locate count function mapping");
}
return function;
}
}
Spero che questo aiuto.
Mi piacerebbe fare la stessa cosa ... ma evitare la soluzione GetSql. –
Sì, questa soluzione era dolorosa, necessaria per ottenere lo sql dai criteri ma non è possibile ottenere i parametri oi valori dai criteri (in modo semplice), quindi avevamo bisogno di un'altra raccolta per archiviare i valori, e hanno bisogno di essere nell'ordine corretto ecc. –
Cosa hai inserito nell'SQL? Non riesco ancora a capire quale risultato ti serva. –