我已经在 java 版本(Hibernate)上解决了这个问题。问题是 RowProjection 函数有点像:
count(*)
这是一个聚合函数:因此,如果您创建一个“分组依据”属性,您的结果是分组行的列表,并且对于每一行,您都有该组的总数。
对我来说,使用 oracle 数据库,为了使其工作,我创建了一个自定义投影,而不是创建函数 count(*),函数是
count(count(*))
并且 group by 子句中的属性没有写在 select ... from 语句中。要做到这一点并不那么简单,问题是您必须提供所有堆栈来创建正确的 sql,所以,我必须使用 java 版本来子类化 2 类:SimpleProjection ProjectionList
之后我的查询生成为:
select count(*), col1, col2 from table1 group by col1, col2
变得
select count(count(*)) from table1 group by col1, col2
结果是由给出的总行
select col1, col2 from table1 group by col1, col2
(可与分页系统一起使用)
如果对您有用,我在这里发布类的 java 版本:
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;
}
}
希望这有帮助。