【问题标题】:Spring Data JPA Pagination - Query creation from method namesSpring Data JPA 分页 - 从方法名称创建查询
【发布时间】:2020-12-18 03:53:23
【问题描述】:

我在 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

【问题讨论】:

  • 你试过包含关键字吗?

标签: java spring jpa pagination spring-data-jpa


【解决方案1】:

尝试包含关键字:

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

【讨论】:

    【解决方案2】:

    首先,不应允许客户端过滤数据。数据过滤逻辑应该在服务器端实现。因此,应覆盖默认的 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);
    

    【讨论】:

      猜你喜欢
      • 2019-08-26
      • 1970-01-01
      • 1970-01-01
      • 2020-08-24
      • 1970-01-01
      • 2017-04-04
      • 2015-12-11
      • 2017-11-08
      • 2020-01-23
      相关资源
      最近更新 更多