CriteriaBuilder.size() 和 Hibernate 的 @Where 注释



我有以下设置:

@Entity
public class Function {
private String name;
@OneToMany(mappedBy = "function", cascade = CascadeType.ALL, orphanRemoval = true)
@Where(clause = "type = 'In'") // <=== seems to cause problems for CriteriaBuilder::size
private Set<Parameter> inParameters = new HashSet<>();
@OneToMany(mappedBy = "function", cascade = CascadeType.ALL, orphanRemoval = true)
@Where(clause = "type = 'Out'") // <=== seems to cause problems for CriteriaBuilder::size
private Set<Parameter> outParameters = new HashSet<>();
}
@Entity
public class Parameter {
private String name;
@Enumerated(EnumType.STRING)
private ParameterType type;
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "function_id")
private Function function;
}

我试图解决的总体问题是找到所有具有outParameter的函数,这些函数具有一组精确的动态名称例如,查找名称与('outParam1', 'outParam2')完全相同的具有outParameter的所有函数

这似乎是一个";精确关系划分";SQL中的问题,所以可能有更好的解决方案,但我做这件事的方式是这样的:

List<String> paramNames = ...
Root<Function> func = criteria.from(Function.class);
Path outParams = func.get("outParameters");
Path paramName = func.join("outParameters").get("name");
...
// CriteriaBuilder Code
builder.and(
builder.or(paramNames.stream().map(name -> builder.like(builder.lower(paramName), builder.literal(name))).toArray(Predicate[]::new)),
builder.equal(builder.size(outParams), paramNames.size()));

我遇到的问题是builder.size()似乎没有考虑到@Where注释。因为";标准生成器代码";嵌套在适用于任何类型实体的通用Specification中,我不能简单地添加query.where()子句。

当一个函数有0个输入参数时,代码可以工作,但当它有更多输入参数时就不工作了。我看了一下生成的SQL,发现它不见了:

SELECT DISTINCT
function0_.id AS id1_37_,
function0_.name AS name4_37_,
FROM
functions function0_
LEFT OUTER JOIN parameters outparamet2_ ON function0_.id = outparamet2_.function_id
AND (outparamet2_.type = 'Out') -- <== where clause added here
WHERE (lower(outparamet2_.name)
LIKE lower(?)
OR lower(outparamet2_.name)
LIKE lower(?))
AND (
SELECT
count(outparamet4_.function_id)
FROM
parameters outparamet4_
WHERE
function0_.id = outparamet4_.function_id) = 2 -- <== where clause NOT added here

感谢任何帮助(无论是用不同的方法解决问题,还是用解决builder.size()不起作用的方法(。

where注释在函数实体中,在子查询中您没有使用该实体,因此操作正确,请尝试使用函数实体作为子查询的根,或者手动实现where。

对于下一个问题,建议您在答案中包含完整的Criteria API代码,以便更精确。

最新更新