当查询实体的子类型的字段时,Hibernate生成IN运算符;使用条件API

时间:2019-02-28 08:09:51

标签: sql hibernate jpa inheritance criteria

想象一下,我有一个域模型,该域模型由4类Fruit(抽象),Apple,Pear和Kiwi(Fruit的子类)组成,并带有区分符列“ type”。假设Apple的类的标识符列值为“ apple”,而Pear的值为“ pear”,猕猴桃的值为“ kiwi”。最后,每个实体都采用“每类表”策略进行映射,因此我们有四个表,分别表示水果,苹果,猕猴桃和梨。

关于我的用例:我有一个要对Fruits进行的搜索查询。我们将搜索成熟的水果,但我们还假设一个苹果有一个甜度场,一个梨有一个厚度场,我们想找到甜度大于10的苹果和梨厚度大于30的苹果。 。我们对新西兰人没有任何特殊要求。

如果我将条件API与元模型一起使用,则必须将我的水果Root对象分别向下转换为Apple和pear,以查询我们需要测试的字段。

代码示例:

 default List<Fruit> find() {
    return findAll((root, query, cb) -> {
        //Note that we DON'T make a kiwiRoot object here (there's no  need...)
        Root<Apple> appleRoot = cb.treat(root, Apple.class);
        Root<Pear> pearRoot = cb.treat(root, Pear.class);
        //... build up a predicate on the root, apple & pear objects...
}

现在,实际的问题是Hibernate使用in运算符生成查询,该运算符仅选择用于构建查询的水果类型!这样我们就可以得到成熟的水果, 但仅 10个甜苹果 30个厚度的梨的水果!由于Hibernate生成了IN运算符,因此我们一路走失。

伪代码SQL示例:

SELECT ... FROM fruit 
LEFT OUTER JOIN ... (Apples)
LEFT OUTER JOIN ... (Pears)
LEFT OUTER JOIN ... (Kiwi) -- The Kiwis DO get joined in the query though...
WHERE
  fruit.type IN ('apple', 'pear') --Where did our Kiwi go?
  ... -- ripeness, sweetness, thickness check...

我已经尝试在OR。谓词上放置fruit.type IN('kiwi'),但是查询被弄乱了,括号没有放在应该去的地方...

PS:这显然是一个过度简化的示例,发生此问题的实际代码确实需要使用条件API,因为查询变得相当复杂。

1 个答案:

答案 0 :(得分:0)

“区分类别”列不应与“按类分类”策略一起使用。

  

注释类型DiscriminatorColumn

     

指定SINGLE_TABLE和JOINED的鉴别符列   继承映射策略。

https://docs.oracle.com/javaee/7/api/javax/persistence/DiscriminatorColumn.html