[英]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.