簡體   English   中英

JPA 搜索字符串、長整型和布爾型

[英]JPA search String, Long and Boolean

我有一個 Spring-Boot 應用程序。 有一個實體:

@Entity
@Table(name = "user")
public class User {
    private Long id;
    private String name;
    private Long schoolId;
    private Boolean isActive;
    // getters and setters
}

我有一個存儲庫:

@Repository
public interface UserRepositoryPageable extends PagingAndSortingRepository<User, Long> {
}

我需要請求按schoolId進行搜索schoolId某個字符串過濾所有字段

像這樣的東西:

@Query("SELECT u FROM User u " +
        "WHERE u.schoolId = :schoolId AND (" +
        "u.id like %:searchVal% OR " +
        "u.name like %:searchVal% OR " +
        "u.isActive like %:searchVal%)")
Page<User> getUserBySchoolIdWithFilter(@Param("schoolId") Long schoolId,
                                       Pageable pageable,
                                       @Param("searchVal") String searchVal);

但是我收到一個異常,因為我嘗試將like應用到LongBoolean

例如,如果我嘗試按“testSearchValue”進行過濾,則會收到以下異常:

java.lang.IllegalArgumentException: 參數值 [%testSearchValue%] 與預期類型 [java.lang.Long (n/a) 不匹配

不幸的是, CASTCONVERT對我不起作用。

那么有什么解決方法嗎?

一些細節

我向這個 API 發送了一個GET請求:

@RequestMapping(path = "users/{schoolId}/search", method = GET)
public ResponseEntity<Page<User>> searchUserBySchoolWithFilter(
                    @PathVariable(value = "schoolId") Long schoolId, Pageable pageable,
                    @RequestParam(value = "searchVal", required = false) String searchVal) {
    return new ResponseEntity<>(userService
                .getUserBySchoolIdWithFilter(schoolId, pageable, searchVal), HttpStatus.OK);
    }

然后在UserService

public Page<User> getUserBySchoolIdWithFilter(Long schoolId, Pageable pageable, String searchVal) {
    return userRepositoryPageable.getUserBySchoolIdWithFilter(schoolId, pageable, searchVal);
}

所以:

在我看來,問題的基本點是將LongBoolean表示為String
也許最好使用nativeQuery 如果是這樣,那么您能否給我一個關於如何將CAST()CONVERT()LIKE子句一起使用的提示?

您是否考慮過Specifications的用法?

使用規范,您可以動態生成 spring 數據查詢的WHERE部分。 為了在 Spring 數據 JPA 查詢中使用規范,您必須擴展org.springframework.data.jpa.repository.JpaSpecificationExecutor接口。 因此,您的用戶存儲庫可能如下所示:

public interface UserRepository extends JpaRepository<User, Long>, JpaSpecificationExecutor<User> {
}

您的搜索方法可能如下所示

public List<User> getAllFilterByString(String text) {

    if(StringUtils.isEmpty(text))
        return userRepository.findAll();

    Specification<User> specification =
            (root, query, cb) -> {
                List<Predicate> predicates = new ArrayList<>();
                predicates.add(cb.like(cb.lower(root.get("name")), "%"+text.toLowerCase()+"%"));

                //check if the text value can be casted to long.
                //if it is possible, then add the check to the query
                try {
                    long longValue = Long.valueOf(text);
                    predicates.add(cb.equal(root.get("id"), longValue));
                }
                catch (NumberFormatException e) {
                    //do nothing, the text is not long
                }

                //check if the text can be casted to boolean
                //if it is possible, then add the check to the query

                Boolean value = "true".equalsIgnoreCase(text) ? Boolean.TRUE :
                        "false".equalsIgnoreCase(text) ? Boolean.FALSE : null;

                if(value != null) {
                    predicates.add(cb.equal(root.get("isActive"), value));
                }

                return cb.or(predicates.toArray(new Predicate[] {}));
            };

    return userRepository.findAll(specification);

}

首先,我們開始在 where 表達式中添加name LIKE %text%部分。

接下來,我們檢查text變量的值是否可以轉換為long 如果可以,那么我們從字符串中取出 long 值並將其添加到 where 查詢中。

最后我們檢查text變量是否可以轉換為布爾值。 如果可以,那么我們也將該檢查添加到查詢中。

例如,如果text變量的值是test1,則 where 部分將是

WHERE name LIKE '%test1%;

如果text變量的值為真,則 where 部分將是

WHERE name LIKE '%true%' OR is_active = true;

最后,如果text變量的值為12,那么 where 部分將是

WHERE name LIKE '%12%' OR id = 12;

注意:當我們按名稱搜索時,我將cb.lower(root.get("name"))text.toLowerCase()到部分,以使搜索不區分大小寫。

暫無
暫無

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

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