【问题标题】:how to group by columns without projection in hibernate criteria?如何在休眠标准中按列分组而不进行投影?
【发布时间】:2023-03-23 20:05:02
【问题描述】:

我试图只获取 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(); 

请帮帮我吗?

【问题讨论】:

  • 如果您尝试获取“only max(xxx)”,您的查询不应该返回唯一结果吗?
  • 与返回assetHistoryIds列表的sql代码具有相同的功能,但使用休眠标准它也投影分组列。我不想在我的结果中对列进行分组,我只想要 max(assetHistoryId)。就像从表中选择 max(assethistoryid)。但是在休眠状态下,我从表中获取了 select max(assethistoryid),assetidentifer,eventnumber。希望你理解
  • 请任何人帮我解决我的问题?
  • @Ranjit,你能解决这个问题吗?

标签: java hibernate hibernate-mapping hibernate-criteria


【解决方案1】:

如果我对您的理解正确,您只需要 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));

【讨论】:

  • 这不适应分组。 @Ranjit 你能解决这个问题吗?
  • @Rishab178 ping...如果您仍然对解决方案感兴趣。 =)
【解决方案2】:

好的,男孩和女孩。我知道这是一个 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();

瞧!

【讨论】:

    猜你喜欢
    • 2011-04-11
    • 2015-07-17
    • 1970-01-01
    • 2017-12-11
    • 1970-01-01
    • 2012-09-06
    • 1970-01-01
    • 1970-01-01
    • 2017-05-25
    相关资源
    最近更新 更多