Reputation: 333
@Repository
@RepositoryRestResource(collectionResourceRel = "myEntity", path = "myEntity")
public interface MyEntity Repository extends JpaRepository<MyEntity, Long>, JpaSpecificationExecutor<MyEntity> {
default Page<MyEntity > findByFilters(Map<String, String> filters, Pageable pageable){
// this is a helper class that handles filtering
Specification<MyEntity > spec = new GenericSpecification<>(filters, MyEntity .class);
return findAll(spec, pageable);
}
MyEntity findByName(String name);
}
I'm using SpringDataRest to generate boilerplate CRUD REST endpoints, but for filtering, i have my own logic based on request params, the only solution i found when reading the SpringDataRest docs when it comes to filtering is to declare NamedQueries like findByName
and this generates something like this : {{entityPath}}/search/{{propertyNameUsingReflexion}}
which takes name
as a param.
that's not enough for my use case.
is there a way to expose my findByFilters
method as an endpoint using SpringDataRest ?
PS : I do not want to create an endpoint in my controllers for each of my entites to do the filtering.
Upvotes: 0
Views: 61
Reputation: 3237
I think I have found a way using the usual method of customising JPA and JDBC repositories.
You need to define another interface which specifies the new method you want to put on the repository:
public interface MyEntitySpecificationExtension {
Page<ChatUser> findByFilters(Map<String, String> filters, Pageable pageable);
}
I have found it to be necessary to create another repository for implementing the specification:
@Repository
public interface MyEntitySpecificationRepository extends JpaRepository<MyEntity, Long>, JpaSpecificationExecutor<MyEntity> {
}
Now implementMyEntitySpecificationExtension, wrapping this repository implementing the specification:
@Component
public class MyEntitySpecificationExtensionImpl implements MyEntitySpecificationExtension {
// note from the docs that the 'Impl' suffix is necessary for JPA to be able to find the class to mixin with the repository
@Autowired
private MyEntitySpecificationRepository myEntitySpecificationRepository;
@Override
public Page<MyEntity> findByFilters(Map<String, String> filters, Pageable pageable) {
// this is a helper class that handles filtering
Specification<MyEntity> spec = new GenericSpecification<>(filters, MyEntity .class);
return myEntitySpecificationRepository.findAll(spec, pageable);
}
}
You can now remove findByFilters and the JpaSpecificationExecutor from MyEntityRepository, and you need it to extend MyEntitySpecificationExtension:
@Repository
@RepositoryRestResource(collectionResourceRel = "myEntity", path = "myEntity")
public interface MyEntityRepository extends JpaRepository<MyEntity, Long>, MyEntitySpecificationExtension {
MyEntity findByName(String name);
}
findByFilters
now appears in the hypermedia list. How to use the filters
query parameter is another question: as I haven't got an implementation of GenericSpecification I haven't been able to test whether it works.
Upvotes: 0