Pagination with spring boot usiing jpa - java

How can I implement a method that return a page of objects using JpaRepository and not PagingAndSortingRepository ?
My repository
public interface GroupRepository extends JpaRepository<Group, Long> {
#Query(value = "SELECT g FROM Group")
Page<Group> listAllByPage(Pageable pageable);
}
My service implementation:
#Override
public
Page<Group> findGroupesByPagination(Pageable pageable) {
return groupeRepository.listAllByPage(pageable);
}
My rest Controller method:
#RequestMapping(value="/groups", method = RequestMethod.GET)
public #ResponseBody Page<Group> list( Pageable pageable){
Page<Group> groupes = groupeServiceImpl.findGroupesByPagination(pageable);
return groupes;
}
Finally I got this error:
Error creating bean with name 'groupServiceImpl': Unsatisfied
dependency expressed through field 'groupeRepository'; nested
exception is org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'groupRepository': Invocation of init
method failed; nested exception is java.lang.IllegalArgumentException:
Validation failed for query for method public abstract
org.springframework.data.domain.Page
rimtrack.org.repository.GroupRepository.listAllByPage(org.springframework.data.domain.Pageable)!

The query can be defined by an annotation somewhere or declared by other means. Consult the documentation of the specific store to find available options for that store. If the repository infrastructure does not find a declared query for the method at bootstrap time, it fails.
You should using Spring Data Jpa method. Reference
Page<T> findAll(Pageable pageable);
Please change repository class.
Exam:
public interface GroupRepository extends JpaRepository<Group, Long> {
Page<Group> findAlll(Pageable pageable);
}

Related

How to create custom Spring Data JPA find method with my own property, specification and pageable?

I'd like to create my own custom Spring Data JPA find method that takes Integer, Specification and Pageable.
I've tried creating method like
Page<Student> findAllByGroupId(Integer id, Specification<Student> specification, Pageable pageable);
But it doesn't work.
User Repository
#Repository
public interface UserRepository<T extends User> extends PagingAndSortingRepository<T, Integer>,
JpaSpecificationExecutor<T> {
}
Student Repository
#Repository
public interface StudentRepository extends UserRepository<Student>{
Page<Student> findAllByGroupId(Integer id, Specification<Student> specification, Pageable pageable);
}
Service
#Override
public Page<Student> getGroupStudents(Integer id, StudentQuery studentQuery, Pageable pageable) {
Specification<Student> specification =
studentSpecification.getSpecification(studentQuery);
return studentRepository.findAllByGroupId(id, specification, pageable);
}
When I try this I get
java.lang.IllegalArgumentException: At least 2 parameter(s) provided but only 1 parameter(s) present in query.
Is there any way to create custom find method that takes Integer, Specification and Pageable?

Spring Data REST - Override repository findAll without creating /search/findAll URL

Is there any way to prevent Spring Data REST from creating a /search URLs for overridden repository methods?
For example the following code results in a /search/findAll URL being generated which duplicates the functionality of the collection resource:
public interface EmployeeRepository extends CrudRepository<Employee, Long>
{
#Override
#Query("SELECT e FROM Empolyee e")
Iterable<Employee> findAll();
}
This is only a cosmetic issue when overriding a single method but if you attempt to override multiple methods with the same function name and different parameters, for example both findAll methods in PagingAndSortingRepository then spring throws an exception because it's attempting to map 2 functions to the same path.
public interface EmployeeRepository extends PagingAndSortingRepository<Employee, Long>
{
#Override
#Query("SELECT e FROM Employee e")
Iterable<Employee> findAll();
#Override
#Query("SELECT e FROM Employee e")
Iterable<Employee> findAll(Sort sort);
#Override
#Query("SELECT e FROM Employee e")
Page<Employee> findAll(Pageable pageable);
}
Results in:
java.lang.IllegalStateException: Ambiguous search mapping detected. Both public abstract java.lang.Iterable uk.co.essl.roster.entity.employee.EmployeeRepository.findAll(org.springframework.data.domain.Sort) and public abstract java.lang.Iterable uk.co.essl.roster.entity.employee.EmployeeRepository.findAll() are mapped to /findAll! Tweak configuration to get to unambiguous paths!
at org.springframework.data.rest.core.mapping.SearchResourceMappings.<init>(SearchResourceMappings.java:60)
at org.springframework.data.rest.core.mapping.RepositoryResourceMappings.getSearchResourceMappings(RepositoryResourceMappings.java:128)
at springfox.documentation.spring.data.rest.EntityContext.searchMappings(EntityContext.java:107)
...
Is there any way to prevent Spring Data REST from creating a /search URLs for overridden repository methods?
I found following trick to solve this issue:
#Override
default Page<Employee> findAll(Pageable pageable) {
return findBy(pageable);
}
#RestResource(exported = false)
Page<Employee> findBy(Pageable pageable);
More other this trick allows you to set default sort order for 'get all records' request:
#Override
default Page<Employee> findAll(Pageable p) {
if (p.getSort() == null) {
// The default sort order
return findBy(new PageRequest(p.getPageNumber(), p.getPageSize(), Sort.Direction.DESC, "myField"));
}
return findBy(pageable);
}
Enjoy! ))
#RestResource(exported=false) just for overridden method will not help 'cause this blocks GET 'all records' request (
#RestResource(exported = false)

Spring Data LDAP using Pageable is it possible?

I use spring Data LDAP, I want return all user but by page. findAll work but return all user.
I try user Page<UserLdap> findAll(Pageable pageable); but I have tise error:
Caused by: org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'userLdapRepository':
Invocation of init method failed;
nested exception is org.springframework.data.mapping.PropertyReferenceException:
No property findAll found for type UserLdap!
full code:
public interface UserLdapRepository extends LdapRepository<UserLdap> {
Set<UserLdap> findAll();
Page<UserLdap> findAll(Pageable pageable);
}
I try add extends PagingAndSortingRepository<UserLdap, Name> but I have the same error.
full code:
public interface UserLdapRepository extends PagingAndSortingRepository<UserLdap, Name>, LdapRepository<UserLdap> {
Set<UserLdap> findAll();
Page<UserLdap> findAll(Pageable pageable);
}
Is it possible using Pageable with Spring Data LDAP please?
EDIT:
I find this code in Spring Data ldap:
public Page<T> findAll(Predicate predicate, Pageable pageable) { ...
What is it a predicate please? If you have a sample, I'm happy :)
it is not possible:
UnsupportedOperationException()
#Override
public Page<T> findAll(Predicate predicate, Pageable pageable) {
throw new UnsupportedOperationException();
}
"Due to specifics of the LDAP protocol, paging and sorting are not supported for Spring LDAP repositories."
See more in https://docs.spring.io/spring-data/ldap/docs/current/reference/html/#ldap.repositories

SDR /search mapping collision

I'm using Spring Data REST with Spring Boot 1.5.4 and I have a trouble.
I defined repository:
public interface TicketRepository extends JpaRepository<Ticket, Long> {
#RestResource(path = "find-by-ticket-list-id")
Page<Ticket> findByTicketListIdOrderByPosition(#Param("ticketListId") Long ticketListId, Pageable pageable);
}
I need a specific GET method. So I defined the controller:
#RepositoryRestController
public class TicketController {
#GetMapping("/tickets/{id}")
public ResponseEntity<?> getTicket(#PathVariable Long id, PersistentEntityResourceAssembler assembler) {
...
}
}
And now, when I try to get a list of search resources, I get an error
Failed to convert value of type 'java.lang.String' to required type
'java.lang.Long'
I understand that this is due to a collision of /tickets/{id} and /tickets/search, but I do not understand how to deal with this. I tried to put #Order before the getTicket method and before TicketController definition, but it did not change anything.
How to resolve both URI's?
Use Regular Expressions in URI Template Patterns:
#GetMapping("/tickets/{id:\\d+}")
public ResponseEntity<?> getTicket(#PathVariable Long id, PersistentEntityResourceAssembler assembler) {
...
}
More info...

Exception using Spring Data JPA and QueryDsl via REST Controller

I'm trying to implement a controller method similar to how is documented in the latest Gosling release train of Spring Data that supports QueryDsl. I've implemented the controller as shown in the example in the docs at http://docs.spring.io/spring-data/jpa/docs/1.9.0.RELEASE/reference/html/#core.web.type-safe. Everything compiles and when I start the application (using Spring Boot 1.2.5.RELEASE), everything starts fine.
However, when I try to call my rest endpoint, I always get the following exception:
org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.mysema.query.types.Predicate]: Specified class is an interface
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:101)
at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.createAttribute(ModelAttributeMethodProcessor.java:137)
at org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor.createAttribute(ServletModelAttributeMethodProcessor.java:80)
My guess is that the QuerydslPredicateArgumentResolver is not being applied to the request, and thus the exception. But I see that the QuerydslPredicateArgumentResolver is registered as a bean when I query the Spring Boot manage endpoint /manage/beans. I have also ensured that #EnableSpringDataWebSupport is on my #Configuration class to no effect.
I have the controller annotated with #BasePathAwareController, since I'm using this with Spring Data REST and I want the methods to be under a similar path as the ones that Spring Data REST exposes. I also tried using #RepositoryRestController, but that didn't seem to matter. However, when using #RestController and putting it under a path that was different then the base path that Spring Data REST is using, things worked. So the question is, should it work?
The entire controller right now is:
#RestController
#RequestMapping(value = "/query")
public class AvailController
{
private final AvailRepository repo;
#Autowired
public AvailController(AvailRepository repository)
{
this.repo = repository;
}
#RequestMapping(value = "/avails", method = GET)
public #ResponseBody Page<Avail> getAvails(Model model,
#QuerydslPredicate(root = Avail.class) Predicate predicate,
Pageable pageable,
#RequestParam MultiValueMap<String, String> parameters)
{
return repo.findAll(predicate, pageable);
}
}
I had the same problem with instantiation of Predicate. In the example:
#Controller
#RequiredArgsConstructor(onConstructor = #__(#Autowired) )
class UserController {
private final UserRepository repository;
#RequestMapping(value = "/", method = RequestMethod.GET)
String index(Model model, //
#QuerydslPredicate(root = User.class) Predicate predicate, //
#PageableDefault(sort = { "lastname", "firstname" }) Pageable pageable, //
#RequestParam MultiValueMap<String, String> parameters) {
(...)
(https://github.com/spring-projects/spring-data-examples/blob/master/web/querydsl/src/main/java/example/users/web/UserController.java#L42 ) is using just #Controller and I was using #RepositoryRestController, that seems to be the reason. #RestController also works for me.
I created https://jira.spring.io/browse/DATAREST-838
I also had this issue when trying to implement a custom controller that mimics the returned value as Spring Data REST. I wanted to inject QuerydslPredicate to the controller method and got the annoying 'BeanInstantiationException'.
I found a work around for this by adding the following configuration file to my application:
#Configuration
#Order(Ordered.HIGHEST_PRECEDENCE )
public class MvcConfig extends WebMvcConfigurerAdapter {
#Autowired
#Qualifier("repositoryExporterHandlerAdapter")
RequestMappingHandlerAdapter repositoryExporterHandlerAdapter;
#Override
public void addArgumentResolvers(
List<HandlerMethodArgumentResolver> argumentResolvers) {
List<HandlerMethodArgumentResolver> customArgumentResolvers = repositoryExporterHandlerAdapter.getCustomArgumentResolvers();
argumentResolvers.addAll(customArgumentResolvers);
}
}
See here for reference: https://jira.spring.io/browse/DATAREST-657

Categories