如何在hibernate标准中按列进行分组而不进行投影?

时间:2015-02-06 13:58:43

标签: java hibernate hibernate-mapping hibernate-criteria

我正在尝试仅获取max(assetHistoryId),但我的下面的代码在结果中将3列max(assetHistoryId),eventId和assetIdentifier撤回。 如何使用条件对列进行分组。 你可以在下面找到我的代码。

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(Projections.projectionList()
            .add(Projections.groupProperty("assetIdentifier"))
            .add(Projections.groupProperty("eventId"))
            .add(Projections.max("assetHistoryId")));
    val = agcriteria.list(); 

请帮帮我吗?

2 个答案:

答案 0 :(得分:0)

如果我理解正确,您只需要max(assetHistoryId)而不需要任何其他列详细信息。 你可以尝试这样的事情:

Criteria agcriteria  = createCriteria(someclass.class);
agcriteria.setProjection(Projections.projectionList()
.add(Projections.max("assetHistoryId")));

你可以添加限制,如果有的话......这样:agcriteria.add(Criteria c);或同一组条件

agcriteria.add(Restrictions.in("eventId", listOfEventIds));
agcriteria.add(Restrictions.ne("action", "T"));
agcriteria.add(
            Restrictions.between("modifyDate", lastProcessedTime,
                    batchStartTime));

答案 1 :(得分:0)

好吧,男孩和女孩。我知道这是一种坏事,而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,因为它将以空列中断,我们正在尝试将其传递。所以,这是下一堂课。可耻的元素列表是私人的,但是我们有足够的吸气剂来实现我们的目标。

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();

Voila!