How to use spring data match example for list attribute - query problem

I would like to ask how to use exampleMatcher for a class with a List attribute. Suppose we have a user who can have several roles at the same time. I want all users with a user role from the database

objects

@Entity(name = "UserEntity") public class User { Private Long id; private String name; private String surname; @OneToOne(cascade = CascadeType.ALL) @JoinColumn private Address address; @ManyToMany(cascade = CascadeType.MERGE, fetch = FetchType.EAGER) @JoinColumn private List<UserRole> roles; } @Entity public class UserRole { private Long id; private String name; } 

I am sending a User class with some attributes for getExampleEntity. I am trying to send a list of selected roles from the user interface.

in the controller

 @Override protected User getExampleEntity() { User clonedUser = new User(); List<UserRole> selectedRole = new ArrayList<>(); 

// this loop simply finds and adds all the roles in db based on the selection from the user interface for (Long roleID: selectedUserRoleIDs) selectedRole.add (userRoleService.find (role identifier)); clonedUser.setRoles (selectedRole); return clonedUser; }

A function from JpaRepository calling the findByExample function with an example Matcher.

  @Override public List<TObjectType> findByExample(int first, int pageSize, String sortField, Sort.Direction sortOrder, TObjectType type) { PageRequest pageRequest = getPageRequest(first, pageSize, sortField, sortOrder); ExampleMatcher exampleMatcher = getExampleMatcher(); Example<TObjectType> example = Example.of(type, exampleMatcher); return repository.findAll(example, pageRequest).getContent(); } /** * Generates an example matcher for the instance of {@link TObjectType}. * This can be overriden if a custom matcher is needed! The default property matcher ignores the "id" path and ignores null values. * @return */ protected ExampleMatcher getExampleMatcher() { return ExampleMatcher.matching() .withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING) .withIgnoreNullValues(); } 

It works like a dream if it sends a user with the attribute name or last name or even with any attribute in the Address class, but it does not work with lists. I would appreciate any advice on how to solve this problem and how I can use findByExample with an TObjectType array as an attribute. Many thanks

EDIT: I found a problem. There is repository.findAll function code (org.springframework.data.repository.query.QueryByExampleExecutor # findAll)

 @Override public <S extends T> Page<S> findAll(Example<S> example, Pageable pageable) { ExampleSpecification<S> spec = new ExampleSpecification<S>(example); Class<S> probeType = example.getProbeType(); TypedQuery<S> query = getQuery(new ExampleSpecification<S>(example), probeType, pageable); return pageable == null ? new PageImpl<S>(query.getResultList()) : readPage(query, probeType, pageable, spec); } 

The generated query does not include the list attribute, but I have no idea why it is included in the Example object. Anyone facing this problem? I assume there is only a setup / annotation issue.

+6
source share
1 answer

First try using a transformer. The example below is for Mongodb, but you can see the approach. In my case, the User class contains a list of roles as strings:

 final ExampleMatcher matcher = ExampleMatcher.matching() .withIgnoreNullValues() .withMatcher("roles", match -> match.transform(source -> ((BasicDBList) source).iterator().next()).caseSensitive()); users = userRepository.findAll(Example.of(criteria, matcher), pageRequest); 
0
source

Source: https://habr.com/ru/post/1014683/


All Articles