簡體   English   中英

Spring Data JPA 分頁 - 從方法名稱創建查詢

[英]Spring Data JPA Pagination - Query creation from method names

我在 User 和 PhoneNumber 之間有一個 OneToMany 關系。 因此一個用戶可以有多個電話號碼。

在前端,我只需要提取登錄用戶的電話號碼,或者如果用戶是管理員,我必須顯示所有用戶的電話號碼。 我已經設法實現了這部分,但我遇到的問題如下:在前端,用戶還有一個“電話號碼”搜索框。 因此,如果用戶或管理員搜索 987(假設是前 3 位數字),則應顯示包含“987”並與其個人資料相關聯的任何電話號碼。 如果用戶是管理員,我應該顯示包含“987”的所有用戶的所有數字。

出於分頁目的,我使用 Spring Paging and Sorting Repository。 到目前為止,我已經嘗試過像這樣的 SQL LIKE 通配符。

    public interface UserRepository extends JpaRepository<User, Integer> {
            //this is used for fetching phone numbers by userName, if user is admin I call findAll()
            Page<User> findByUserName(String userName, Pageable pageable);

            //this is used for fetching phone numbers by username by phoneNo LIKE
            Page<User> findByUserNameAndPhoneNumbersPhoneNoLike(String userName,String phoneNo, Pageable pageable);
    }

問題是 LIKE 似乎不起作用。 無論如何,它都會返回與用戶關聯的所有電話號碼,並且會忽略我傳入的任何內容,因此是“%987%”。 因此,如果我有 2 個與用戶 X 關聯的電話號碼(987123 和 321432),它將返回兩個而不是僅返回“987123”。

有沒有人知道我如何查詢這個但作為回報來獲取 Spring 可分頁對象? 我認為從方法名稱創建查詢的功能不足以滿足目的,但我仍然需要可分頁對象作為前端的所有其余實現,服務層基於此。 工作中的某人建議我應該使用 JPA 標准,但我不知道該怎么做,因此作為回報我可以獲得可分頁對象

用戶類

@Entity
    @Table(name="USER")
    public class User implements Serializable{

        @Id @GeneratedValue(strategy=GenerationType.IDENTITY)
        private Integer id;

        @NotEmpty
        @Column(name="USER_ID", unique=true, nullable=false)
        private String userName;

        @OneToMany(fetch = FetchType.EAGER)
        @JoinColumn(name="USER_ID")
        private Set<PhoneNumer> phoneNumbers;

        @NotEmpty
        @JsonIgnore
        @ManyToMany(fetch = FetchType.LAZY)
        @JoinTable(name = "USER_USER_PROFILE",
                joinColumns = { @JoinColumn(name = "USER_ID") },
                inverseJoinColumns = { @JoinColumn(name = "USER_PROFILE_ID") })
        private Set<UserProfile> userProfiles = new HashSet<UserProfile>();
        //Getters and Setters

電話號碼類

@Entity
@Table(name = "PHONE_NUMBER")
public class PhoneNumber {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "ID")
    private long id;

    @Column(name = "PHONE_NUMBER")
    private String phoneNo;
    //Getters and Setters

嘗試包含關鍵字:

Containing
findByFirstnameContaining
… where x.firstname like ?1 (parameter bound wrapped in %)

Page<User> findByUserNameAndPhoneNumbersPhoneNoContaining(String userName,String phoneNo, Pageable pageable);

文檔: https : //docs.spring.io/spring-data/jpa/docs/current/reference/html/#repository-query-keywords

首先,不應該允許客戶端過濾數據。 數據過濾邏輯應該在服務器端實現。 因此,默認 findAll() 應該被覆蓋以合並此行為,如下所示:

@Override
@Query(
        "select p from User u join u.phoneNumbers p where "
        + "u.userId = ?#{@userService.getUserId()} or "
        + "?#{@userService.isAdmin()}"
)
Page findAll(Pageable pageable);

userService 將具有如下通用結構 - 用適當的邏輯填充函數:

@Service("userService")
@Transactional
public class UserServiceJPA {

    public Integer getUserId(){
        /**
         * This function should return current logged in user's id from db
         */
    }
    
    public boolean isAdmin(){
        /**
         * This function should return true or false based on current logged in user
         */
    }
}

這完成了您問題的第一部分。
要按部分電話號碼定義搜索,請使用以下代碼。

@Query(
            "select p from PhoneNumber p where "
            + "("
            + "     p.user.userId = ?#{@userService.getUserId()} or "
            + "     ?#{@userService.isAdmin()} "
            + ") "
            + "and "
            + "p.phoneNo like :#{#partialPhone}%"
    )
    @RestResource(path="partialPhone")
    Page findMatchingPhoneNumbers(
            @Param("partialPhone")String partialPhone,
            Pageable pageable);

暫無
暫無

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

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