簡體   English   中英

Spring 數據規范 - 帶連接的 RSQL

[英]Spring Data Specifications - RSQL with join

我正在嘗試使用規范和 RSQL 開發搜索 API。 遵循本教程 - https://www.baeldung.com/rest-api-search-language-rsql-fiql

我有一個與 UserProfile 有 OneToOne 關系的 User 實體。

@Entity
public class User{

    @Column(nullable = false)
    private String firstName;

    @OneToOne(targetEntity = UserProfile.class, fetch = FetchType.EAGER)
    @JoinColumn(nullable = false, name = "user_profile_id")
    private UserProfile userProfile;
...

@Entity
public class UserProfile{

    @Column(nullable = false)
    private String education;

    ...

和謂詞函數,

@Override
public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
    List<Object> args = castArguments(root);
    Object argument = args.get(0);

    switch (RsqlSearchOperation.getSimpleOperator(operator)) {

    case EQUAL: {
            if (argument instanceof String) {               
                return builder.like(root.get(property), argument.toString().replace('*', '%'));
            } else if (argument == null) {
                return builder.isNull(root.get(property));
            } else {
                return builder.equal(root.get(property), argument);
            }
        }
        case NOT_EQUAL: {

....

當我使用參數 ?search=firstName==John 調用 API 時,它會按預期返回結果。 我需要的是按教育搜索並返回具有該教育的用戶。 我嘗試使用 Join 如下,但它不起作用。

if (argument instanceof String) {
                Join<User, UserProfile> profileJoin = root.join("user_profile_id");

                return builder.like(root.get(property), profileJoin.get(property));
            } else if (argument == null) {

任何具有泛型的解決方案都會非常有幫助。

看起來泛型沒有具體的解決方案。 所以我做到了,這接近於通用。

switch (RsqlSearchOperation.getSimpleOperator(operator)) {

        case EQUAL: {
            if (doesClassContainProperty(UserProfile.class, property)) {
                Join<User, UserProfile> profileJoin = root.join("user_profile_id");
                return builder.equal(profileJoin.get(property), argument);
            } else {
                return builder.equal(root.get(property), argument);
            }
        }

這是檢查傳遞的參數是否在根類或加入類中的方法

public boolean doesClassContainProperty(Class<?> genericClass, String fieldName) {
        return Arrays.stream(genericClass.getDeclaredFields()).anyMatch(f -> f.getName().equals(fieldName));
    }

我想向您推薦另一個庫,它可以讓您構建動態過濾器而不必弄亂編碼,它支持邏輯運算符、比較器、枚舉、日期、布爾值、搜索關系/連接(沒有 n+1 查詢問題)、函數,以及更多: https : //github.com/turkraft/spring-filter

示例查詢:

/search?filter= average (ratings) > 4.5 and brand.name in ('audi', 'land rover') and (year > 2018 or km < 50000) and color : 'white' and notices is empty

用法:

@GetMapping(value = "/search")
public List<Entity> search(@EntityFilter Specification<Entity> spec, Pageable page) {
  return repo.findAll(spec, page);
}

不要忘記依賴:

<dependency>
    <groupId>com.turkraft</groupId>
    <artifactId>spring-filter</artifactId>
    <version>0.9.5</version>
</dependency>

暫無
暫無

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

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