【问题标题】:CriteriaBuilder.size() and Hibernate's @Where annotationCriteriaBuilder.size() 和 Hibernate 的 @Where 注解
【发布时间】:2020-12-28 00:46:19
【问题描述】:

我有以下设置:

@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;
}

我要解决的总体问题是找到所有具有outParameters 且具有精确动态名称集的函数。 例如查找名称为 ('outParam1', 'outParam2')outParameters 的所有函数

这似乎是 SQL 中的“exact relational division”问题,因此可能有更好的解决方案,但我的做法是这样的:

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 注释。因为“CriteriaBuilder 代码”嵌套在一个通用的 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() 不起作用)。

【问题讨论】:

    标签: sql hibernate jpa spring-data-jpa criteria-api


    【解决方案1】:

    where注解在函数实体中,在子查询中你没有使用该实体所以操作是正确的,尝试使用函数实体作为子查询的根,或者手动实现where。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-12-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-29
      • 1970-01-01
      • 2012-11-23
      • 1970-01-01
      相关资源
      最近更新 更多