Java Projections.count()和Projections.countDistinct()都产生相同的查询
编辑:我已经完全编辑了这篇文章,所以对我问题的新描述包括了所有细节,而不仅仅是我以前认为相关的内容。也许这个新的描述将有助于解决我面临的问题 我有两个实体类,Customer和CustomerGroup。客户和客户群之间的关系有很多种。客户组在customer类中按以下方式进行注释Java Projections.count()和Projections.countDistinct()都产生相同的查询,java,hibernate,criteria,Java,Hibernate,Criteria,编辑:我已经完全编辑了这篇文章,所以对我问题的新描述包括了所有细节,而不仅仅是我以前认为相关的内容。也许这个新的描述将有助于解决我面临的问题 我有两个实体类,Customer和CustomerGroup。客户和客户群之间的关系有很多种。客户组在customer类中按以下方式进行注释 @Entity public class Customer { ... @ManyToMany(mappedBy = "customers", fetch = FetchType.LAZY) publi
@Entity
public class Customer {
...
@ManyToMany(mappedBy = "customers", fetch = FetchType.LAZY)
public Set<CustomerGroup> getCustomerGroups() {
...
}
...
public String getUuid() {
return uuid;
}
...
}
这个查询正是我想要的,但有一个例外。由于一个客户可以属于多个CustomerGroup,因此左加入CustomerGroup将导致重复的Customer对象。因此,count(*)
将给出一个假值,因为它只计算有多少个结果。我需要通过使用Projections.countDistinct(“uuid”)获得独特客户的数量,这是我期望实现的代码>-投影。由于某些原因,如您所见,投影仍将导致count(*)
查询,而不是预期的count(distinct uuid)
。将投影countDistinct
替换为仅count(“uuid”)
将产生完全相同的查询
我是做错了什么还是这是一个错误
===
“问题”解决了。原因:PEBKAC(键盘和椅子之间存在问题)。我的代码中有一个分支,但没有意识到该分支已被执行。该分支使用了rowCount()而不是countDistinct()。我想这是因为您的“id”字段是唯一的字段,hibernate知道这一点。
当您使用“distinct”时,查询是否给出不同的结果?可能字段ID被定义为唯一的?尝试使用不同的字段,该字段不是唯一的。尝试在类CountProjection中调试方法toSqlString。看着代码,我只能想象这不是真的;我认为没有其他理由不包括distinct:
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();
}
问候,
问题解决了。原因:PEBKAC(键盘和椅子之间存在问题)。我的代码中有一个分支,但没有意识到该分支已被执行。该分支使用了rowCount()而不是countDistinct()
之后
cr.setProjection(Projections.countDistinct(“memberId”)
SQL结果为计数(memberId)
bo不计数(不同的成员ID)
调试后
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”
公共类AggregateProject扩展了SimpleProject{
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 );
}
尝试使用另一个字段,但结果仍然是count(*)。事实上,我给Projections.countDistinct()指定的参数是什么并不重要,甚至“foobar”结果在同一查询中。如果您的查询包含左联接,请显示您在其中指定此左联接的其余条件代码。如果您仅使用条件创建基本查询,然后手动追加左联接:不是这样做的:)我已编辑问题,以包含与我的问题相关的所有代码。对于ot她在同一个问题上苦苦挣扎,请看这个问题:
public final class Projections {
public static CountProjection countDistinct(String propertyName) {
return new CountProjection(propertyName).setDistinct();
}
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;
}
}
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 );
}