好的,男孩和女孩。我知道这是一个 necro,Hibernate Criteria Api 很久以前就被弃用了。但是仍然有系统使用这个 API,所以希望它有用。
我找不到使用内置休眠投影的方法,所以我决定自己制作。首先,我们需要创建一个新的投影类,它不会在 SELECT 子句中产生任何内容,但在 group 子句中仍然有它。
public class NoPropertyGroupProjection extends SimpleProjection {
private String propertyName;
protected NoPropertyGroupProjection(String propertyName) {
this.propertyName = propertyName;
}
@Override
public boolean isGrouped() {
return true;
}
@Override
public Type[] getTypes(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
return new Type[] { };
}
@Override
public String toSqlString(Criteria criteria, int position, CriteriaQuery criteriaQuery) throws HibernateException {
return "";
}
@Override
public String toGroupSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
return StringHelper.join( ", ", criteriaQuery.getColumns( propertyName, criteria ) );
}
@Override
public String toString() {
return propertyName;
}
}
这是我拥有的 Hibernate 版本的 PropertyProjection 的副本,但做了一些更改。
它不会单独工作(强制它单独工作非常复杂),但在大多数情况下,我们仍然需要选择一些东西。
所以接下来我们需要修复 ProjectionList,因为它会与我们试图传递它的空列中断。所以,这是下一节课。 elements 列表是私有的,但我们有足够的 getter 来实现我们的目标。
public class ProjectionListWithOnlyGroupBySupport extends ProjectionList {
@Override
public String toSqlString(Criteria criteria, int loc, CriteriaQuery criteriaQuery) throws HibernateException {
final StringBuilder buf = new StringBuilder();
String separator = "";
for ( int i = 0; i < this.getLength(); i++ ) {
Projection projection = this.getProjection(i);
String addition = projection.toSqlString( criteria, loc, criteriaQuery );
if (!"".equals(addition)) {
buf.append(separator).append(addition);
loc += getColumnAliases(loc, criteria, criteriaQuery, projection).length;
separator = ", ";
}
}
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 final class AdvancedProjections {
public static NoPropertyGroupProjection groupBy(String propertyName) {
return new NoPropertyGroupProjection( propertyName );
}
public static ProjectionList projectionList() {
return new ProjectionListWithOnlyGroupBySupport();
}
}
创建完所有这些类后,我们可以更改问题中的代码:
final Criteria agcriteria = createCriteria(someclass.class);
agcriteria.add(Restrictions.in("eventId", listOfEventIds));
agcriteria.add(Restrictions.ne("action", "T"));
agcriteria.add(
Restrictions.between("modifyDate", lastProcessedTime,
batchStartTime));
agcriteria.setProjection(AdvancedProjections.projectionList()
.add(Projections.max("assetHistoryId"))
.add(AdvancedProjections.groupBy("assetIdentifier"))
.add(AdvancedProjections.groupBy("eventId")));
val = agcriteria.list();
瞧!