簡體   English   中英

JPA 條件生成器僅在連接列不包含特定值時返回實體

[英]JPA criteria builder only return entity if join column does not contain a certain value

我有兩個班級:

@Entity
@Table(name = "foo")
data class Foo {
  @Id
  val id: UUID
  // a lot more values

  @ElementCollection(fetch = FetchType.EAGER)
  @CollectionTable(name = "foo_bar", joinColumns = [JoinColumn(name = "foo_bar_id")])
  val bars: Set<FooBar>?
}

data class FooBar {
  val fooBarId: UUID
  val bar: Bar
  val validUntil: Instant
}

目前,我使用 Predicate 和 CriteriaBuilder 對此實體進行了廣泛搜索 function。 我希望能夠在我們的搜索中僅包含 Foo 對象,這些對象在其 FooBar JoinColumn 行中具有特定的 Bar 值,而 function 僅在沒有任何joinColumn 行具有該特定 Bar 值的情況下返回 FooBar Object。

我現在所擁有的是:



    fun searchPaged(
        // numerous criteria values
        flipFilterOnBar: Boolean?,
        bar: Bar?,
        pageable: Pageable
    ): Page<Foo> {
  return findAll({ root, _, cb ->
    
    val predicates = mutableListOf<Predicate>(
                cb.or(
                   //some criteria
                )
            )

     //more criteria
     //
     //

      if (bar != null) {
                val joinColumn: Join<Foo, FooBar> = root.join<Foo?, FooBar?>("bars", JoinType.INNER)
                if (flipFilterOnBar == true) { //Nullable boolean
                    
                    // this part makes the query return a row for each join column and filters out only the filtered value (returning more rows than if this clauses was not added.
                    predicates.add(
                    cb.notEqual(joinColumn.get<Bar>("bar"), bar)
                    )
                } else {
                    predicates.add(
                        cb.equal(joinColumn.get<Bar>("bar"), bar)
                    )
                }
            }

            cb.and(*predicates.toTypedArray())
        }, pageable)

我想知道如果沒有 FooBar 行包含指定的 Bar 值,我如何使用此處的條件構建器僅返回 Bar 實體。 我現在編寫它的方式將所有 Foo 和 FooBar 行連接在一起,並且只過濾具有指定 Bar 值的組合行,返回不是我想要的其他組合行。

例如,如果我有一個包含 3 個 FooBar 的 Foo,我想過濾掉所有具有值為“b”的 Bar 的 Foo。 查詢檢索此 Foo 3 次(每個 Bar 元素一次),然后僅過濾其中包含值為“b”的 Foo 的組合行。 返回其他兩行。 我希望查詢不返回任何這些行,因為其中一行包含值“b”。

嘗試使用類似於所有通過先前謂詞的 foos 的謂詞,並且其 id 不在 foos 的 id 集合中,foobars 的 bar 值為“b”。

        Subquery<UUID> subquery = criteriaQuery.subquery(UUID.class);
        Root<Foo> fooSubqueryRoot = subquery.from(Foo.class);
        Join<Foo, FooBar> fooBarSubqueryJoin = fooSubqueryRoot.join("bars");
        Join<FooBar, Bar> barSubqueryJoin = fooBarSubqueryJoin.join("bar");
        subquery.where(cb.equal(barSubqueryJoin.get("value"), "b"));
        //foos ids of foos with foobars whose bar value is "b"
        subquery.distinct(true).select(fooSubqueryRoot.get("id"));
        //exclude foos with foobars whose bar value is "b"
        predicates.add(root.get("id").in(subquery).not());

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM