Multi column search using Specifications Spring Data Jpa within associated entity?

后端 未结 1 713
情歌与酒
情歌与酒 2020-12-20 08:48

I am taking this question Perform multi column search on Date, Integer and String Data type fields of Single Table? and This method must return a result of type Specificatio

相关标签:
1条回答
  • 2020-12-20 09:45

    If you take a look at my post actually I have a solution for join

    @Override
    public Specification<User> getFilter(UserListRequest request) {
        return (root, query, cb) -> {
            query.distinct(true); //Important because of the join in the addressAttribute specifications
            return where(
                where(firstNameContains(request.search))
                    .or(lastNameContains(request.search))
                    .or(emailContains(request.search))
            )
                .and(streetContains(request.street))
                .and(cityContains(request.city))
                .toPredicate(root, query, cb);
        };
    }
    
    private Specification<User> firstNameContains(String firstName) {
        return userAttributeContains("firstName", firstName);
    }
    
    private Specification<User> lastNameContains(String lastName) {
        return userAttributeContains("lastName", lastName);
    }
    
    private Specification<User> emailContains(String email) {
        return userAttributeContains("email", email);
    }
    
    private Specification<User> userAttributeContains(String attribute, String value) {
        return (root, query, cb) -> {
            if(value == null) {
                return null;
            }
    
            return cb.like(
                cb.lower(root.get(attribute)),
                containsLowerCase(value)
            );
        };
    }
    
    private Specification<User> cityContains(String city) {
        return addressAttributeContains("city", city);
    }
    
    private Specification<User> streetContains(String street) {
        return addressAttributeContains("street", street);
    }
    
    private Specification<User> addressAttributeContains(String attribute, String value) {
        return (root, query, cb) -> {
            if(value == null) {
                return null;
            }
    
            ListJoin<User, Address> addresses = root.joinList("addresses", JoinType.INNER);
    
            return cb.like(
                cb.lower(addresses.get(attribute)),
                containsLowerCase(value)
            );
        };
    }
    
    private String containsLowerCase(String searchField) {
        return "%" + searchField.toLowerCase() + "%";
    }
    

    Here you can see how I search the users by their address columns (city and street).

    EDIT: Also you cannot use the @Query annotation that much dinamically (you van insert parameter values dinamically, but not parameters. That's where Specificaion is handy)

    EDIT2: I know this is not the 2.x.x Spring version, but 1.5.x, but the idea is the same for joins.

    0 讨论(0)
提交回复
热议问题