gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-03 18:08:19 25 4
gpt4 key购买 nike

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

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


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

customer groups类中的customer reference按如下方式标注


@Entity
public class CustomerGroup {
...
@ManyToMany
public Set<Customer> getCustomers() {
...
}

...

public String getUuid() {
return uuid;
}
...
}

请注意,CustomerGroup 和 Customer 类也有一个 UUID 字段。 UUID 是一个唯一的字符串(在数据模型中没有强制唯一性,如您所见,它被处理为任何其他普通字符串)。

我想做的是获取不属于任何客户组或客户组是“有效组”的所有客户。客户组的有效性由有效 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 (
?, ?
)

查询正是我想要的,但有一个异常(exception)。由于一个 Customer 可以属于多个 CustomerGroup,因此左加入 CustomerGroup 将导致重复的 Customer 对象。因此 count(*)会给出一个错误的值,因为它只计算有多少结果。我需要获得唯一客户的数量,我希望通过使用 Projections.countDistinct("uuid"); 来实现这一点-投影。出于某种原因,如您所见,投影仍将导致 count(*)。查询而不是预期的 count(distinct uuid) .更换投影 countDistinct只有 count("uuid")将产生完全相同的查询。

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

===

“问题”解决了。原因:PEBKAC(键盘和椅子之间存在问题)。我的代码中有一个分支,但没有意识到该分支已被执行。该分支使用 rowCount() 而不是 countDistinct()。

最佳答案

3.5.1 有问题

之后

cr.setProjection(Projections.countDistinct("memberId"));

SQL 结果为 count(memberId)

不计数(不同的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;
}
}

和 ... 在 AggregateProjection 中仅使用 getFunctionName() = functionName = "count"!!!

公共(public)类 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 );
}

关于java - Projections.count() 和 Projections.countDistinct() 都产生相同的查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2318952/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com