代码之家  ›  专栏  ›  技术社区  ›  KCL

Projections.count()和projects.countDistinct()都产生相同的查询

  •  2
  • KCL  · 技术社区  · 16 年前

    编辑:我已经完全编辑了这篇文章,所以我的问题的新描述包括了所有的细节,而不仅仅是我以前认为相关的内容。也许这个新的描述将有助于解决我面临的问题。

    我有两个实体类,Customer和CustomerGroup。顾客与顾客群体之间的关系是多种多样的。在customer类中,按以下方式对客户组进行注释。

    
    @Entity
    public class Customer {
      ...
      @ManyToMany(mappedBy = "customers", fetch = FetchType.LAZY)
      public Set<CustomerGroup> getCustomerGroups() {
        ...
      }
      ...
      public String getUuid() {
        return uuid;
      }
      ...
    }
    
    

    
    @Entity
    public class CustomerGroup {
      ...
      @ManyToMany
      public Set<Customer> getCustomers() {
        ...
      }
    
      ...
    
      public String getUuid() {
        return uuid;
      }
      ...
    }
    
    

    我创建了以下条件查询

    
    Criteria criteria = getSession().createCriteria(Customer.class);
    criteria.setProjection(Projections.countDistinct("uuid"));
    criteria = criteria.createCriteria("customerGroups", "groups", Criteria.LEFT_JOIN);
    
    List<String> uuids = getValidUUIDs();
    Criterion criterion = Restrictions.isNull("groups.uuid");
    if (uuids != null && uuids.size() > 0) {
      criterion = Restrictions.or(criterion, Restrictions.in(
          "groups.uuid", uuids));
    }
    criteria.add(criterion);
    
    

    在执行查询时,它将导致以下SQL查询

    
    select
        count(*) as y0_ 
    from
        Customer this_ 
    left outer join
        CustomerGroup_Customer customergr3_ 
        on this_.id=customergr3_.customers_id 
    left outer join
        CustomerGroup groups1_ 
        on customergr3_.customerGroups_id=groups1_.id 
    where
        groups1_.uuid is null 
        or groups1_.uuid in (
            ?, ?
        )
    
    

    这个查询正是我想要的,但有一个例外。由于一个客户可以属于多个CustomerGroups,左键加入CustomerGroups将导致重复的Customer对象。因此 count(*) Projections.countDistinct("uuid"); -投影。由于某种原因,正如您所见,投影仍然会导致 计数(*) 查询而不是预期的 count(distinct uuid) . 更换突出部分 countDistinct count("uuid") 将产生完全相同的查询。

    我做错什么了还是这是一个错误?

    ===

    5 回复  |  直到 9 年前
        1
  •  4
  •   OxUlsen    16 年前

    这是3.5.1中的错误

    cr.setProjection(projects.countDistinct(“memberId”));

    SQL结果为count(memberId)

    调试后。。。。

    public final class Projections {
    
        public static CountProjection countDistinct(String propertyName) {
            return new CountProjection(propertyName).setDistinct();
        }
    

    distinct被注意到但没有被使用。

    public class CountProjection extends AggregateProjection {
        private boolean distinct;
    
        protected CountProjection(String prop) {
            super("count", prop);
        }
    
        public String toString() {
            if ( distinct ) {
                return "distinct " + super.toString();
            }
            else {
                return super.toString();
            }
        }
    
        public CountProjection setDistinct() {
            distinct = true;
            return this;
        }
    }
    

    还有。。。在聚合投影中 只使用getFunctionName()=functionName=“count”!!!

    公共类AggregateProjection扩展了SimpleProjection{

    protected AggregateProjection(String functionName, String propertyName) {
        this.functionName = functionName;
        this.propertyName = propertyName;
    }
    
    public String getFunctionName() {
        return functionName;
    }
    
    public String getPropertyName() {
        return propertyName;
    }
    
        ...
    
    public String toSqlString(Criteria criteria, int loc, CriteriaQuery criteriaQuery)
            throws HibernateException {
        final String functionFragment = getFunction( criteriaQuery ).render(
                buildFunctionParameterList( criteria, criteriaQuery ),
                criteriaQuery.getFactory()
        );
        return functionFragment + " as y" + loc + '_';
    }
    
    protected SQLFunction getFunction(CriteriaQuery criteriaQuery) {
        return getFunction( getFunctionName(), criteriaQuery );
    }
    
        2
  •  3
  •   KCL    16 年前

        3
  •  1
  •   Stijn Geukens    16 年前

        public String toSqlString(Criteria criteria, int position, CriteriaQuery criteriaQuery) 
    throws HibernateException {
        StringBuffer buf = new StringBuffer();
        buf.append("count(");
        if (distinct) buf.append("distinct ");
        return buf.append( criteriaQuery.getColumn(criteria, propertyName) )
            .append(") as y")
            .append(position)
            .append('_')
            .toString();
    }
    

    当做
    斯泰恩

        4
  •  0
  •   Fortega    16 年前

    当您使用'distinct'时,查询是否给出不同的结果?

        5
  •  0
  •   Thomas Lötzer    16 年前

    也许字段ID被定义为唯一的?尝试使用不同的字段,这不是唯一的。