Spring boot repository query to return a ordered result - spring-boot

public interface StudentRepository extends MongoRepository<Student, String> {
Page<Student> findByIdInAndNameLike(List<String> ids, String name, Pageable pageable);
}
In Service layer :
Pageable pageable = PageRequest.of(page, size);
studentRepository.findByIdInAndNameLike(idList, name, pageable );
Here this idList is an ordered list. And I need to get the search results according to the order of that idList.
eg : List<String> idList= Arrays.asList("123", "111", "213");
So here the Student with id 123 should come first. And student with id 213 should come last.

As per this tutorial u have to provide the 3rd parameter to PageRequest which exactly does the sorting for you
Pageable sortedByName = PageRequest.of(page, size, Sort.by("id"));

Related

Spring Data JDBC - Pageable on custom Query

On my Project I have a Repository that extends CrudRepository. Inside there I have a custom query:
public interface CustomerRepository extends CrudRepository<Customer, Long> {
#Query("select * from person where firstname = :firstname")
List<Customer> findByFirstname(#Param("firstname") String firstname, Pageable pageable);
}
in my Service-Class I try to put the List in a Pageable - Object like:
... getPageableCustomer(String firstname, Pageable pageable){
// => By using "Sol" I got 90 matching entries
List<Customer> custList = customerRepository.findByFirstname(firstname, pageable);
Page<Customer> custPage = new PageImpl<Customer>(custList, pageable, custList.size());
return custPage;
}
the return value includes the complete List "custList". What would be the best way to get a pageable object with specified offset and size?
One option could be to use
customer.subList(fromIndex, toIndex)
but that feels wrong. Also because of Loading all Data inside the list instead of just getting data by size and offset as parameterized with pageable.
Remark: In case of using Page inside the Repository I ´ll get org.springframework.dao.IncorrectResultSizeDataAccessException: Incorrect result size: expected 1, actual 88
There is also a open Improvement on Jira that could be found here:
https://jira.spring.io/browse/DATAJDBC-554?filter=-3
hope for some help...
I got a response on the JIRA-Issue from Dirk Luijk (Thx Dirk :))
https://jira.spring.io/browse/DATAJDBC-554?filter=-3
interface FooRepository extends PagingAndSortingRepository<FooEntity, Long> {
List<FooEntity> findAllByBar(String bar, Pageable pageable);
Long countAllByBar(String bar);
}
And then combining those 2 queries like this:
List<FooEntity> fooList = repository.findAllByBar("...", pageable);
Long fooTotalCount = repository.countAllByBar("...");
Page<FooEntity> fooPage = PageableExecutionUtils.getPage(fooList, pageable, () -> fooTotalCount);
"the mistake in your workaround is your custom query. In Spring Data JDBC 2.0 you don't need to use that, except for special queries but they won't support pageables."
Possible Parameters could be found:
https://docs.spring.io/spring-data/jdbc/docs/current/reference/html/#jdbc.query-methods
Thx Dirk,
I also find a workaround to get it running with a custom Query. Just use limit, offset and orderBy as additional Parameter like so:
#Query("select * from person where firstname = :name order by :order limit :size offset :offset")
List<Customer> findByFirstNameCustomQuery(#Param("name") String name, Pageable page, #Param("offset") long offset,
#Param("size") long size, #Param("order") String order);
And than change the call inside the Service like:
List<Customer> custList = customerRepository.findByFirstNameCustomQuery(firstname, pageable, ....

How to perform sort with multiple fields on custom query JPQL with Spring Pageable

I am using Spring's Pageable to sort the columns.
A working example is below:
Pageable pageable = PageRequest.of(0, countOfBookData.intValue(), getSortingDirection(sortingOrder), sortingField);
Where sortingOrder = ASC and sortingField = bookName
Here is the query
#Query("SELECT bs FROM BookSummary bs WHERE bs.bookId=:bookId")
List<Books> getBookDetails(#Param("bookId") Integer bookId, Pageable pageable)
But I got stuck when I need to perform this sort on Custom my custom query.
So I have no idea how I can perform the sorting using Pageable for below custom query:
Public List<Tuple> getBookDetails(Integer bookId){
String query = "SELECT book.bookCd as bookCode, "
+ "book.name as bookName"
+ "FROM Book book WHERE book.bookId=:bookId";
return entityManager.createQuery(query , Tuple.class).setParameter("bookId", bookId).getResultList();
}
The same as in the first custom query but using the Projection, for example:
public interface BookDetails {
String getBookCode();
String getBookName();
}
#Query("select b.bookCd as bookCode, b.name as bookName from Book b where b.bookId = ?1")
List<BookDetails> getBookDetails(Integer bookId, Pageable pageable);
Note that projection method names must match with corresponding aliases in the query.
Or without the query:
List<BookDetails> getAllById(Integer bookId, Pageable pageable);

Oracle Parallel Hint on Spring Data JPA Specification

Is it possible to use parallel hint on the spring data jpa specification? org.hibernate.jpa.QueryHints package does not contain PARALLEL hint.
I added a comment like in the example below. But I couldn't see the running query.
Calling find method with specifications:
CarSpecifications carSpecifications = new CarSpecifications(car);
List<Car> carList = carRepository.findAll(carSpecifications, pageable);
Repository:
#Override
public Page<T> findAll(Specification<T> spec, Pageable pageable) {
TypedQuery<T> query = getQuery(spec, pageable);
query.setHint("org.hibernate.comment", "Example Comment");
return pageable == null ? new PageImpl<T>(query.getResultList()) : readPage(query, pageable, spec);
}
or in the interface
#QueryHints({ #QueryHint(name = "org.hibernate.comment", value ="Example Comment") })
Page<T> findAll(Specification<T> spec, Pageable pageable);
Thanks.

Springboot JPA Pageable not working for page number greater then 0

I want to get the Results Paginated, The below code works fine if the request is made with page parameter set to 0 but it doesn't work for page>0 like page=1 or page=2 or page=3 etc.
Here is my RequestMapping
MyResponse getSample(#ModelAttribute MyRequest MyRequest) {
Pageable pageRequest = new PageRequest(MyRequest.page, MyRequest.size)
MyModule.findSamples(MyRequest, pageRequest)
}
class MyRequest {
MyQueryType queryType
String searchTerm
#Min(value = 0L, message = 'Offset must be greater than or equal to 0')
int offset = 0
#Min(value = 0L, message = 'Offset must be greater than or equal to 0')
int page = 0
#Min(value = 1L, message = 'Limit must be greater than or equal to 1')
int limit = 100
#Min(value = 1L, message = 'Limit must be greater than or equal to 1')
int size = 5
}
MyModule:Code inside my Module
MyResponse findSamples(MyRequest MyRequest, Pageable pageRequest) {
log.info("Page Information Set "+pageRequest.pageNumber+pageRequest.pageSize)
Page<SamplesPO> pages = null
pages = MyRepository.findAllById(MyRequest.Id, pageRequest)
}
Repository Code:
public interface SampleRepository extends JpaRepository<Sample, Long> {
#Query('''
select e.Samples
from ParentSampleTable e
where e.Id = :Id
''')
Page<Sample> findAllById(#Param('Id') String Id, Pageable pageRequest)
}
Read PageRequest java docs before Using below code. PageRequest
request works on page number(starts from index 0 to 1,2,3 and so
on) and the size( limit you want)
Sort sort = new Sort(Sort.Direction.DESC, "mfgDate");
Pageable pageable = new PageRequest(pageNumber, pageSize, sort);
#Repository
public interface BikeRepository extends MongoRepository<Bike, String> {
Page<Bike> findByCompanyId(String companyId, Pageable pageable);
}
You could try extracting the id with #PathParam
Method getSample annotated with #GetMapping with params (#PathParam("id") String id, Pageable pageable) and it could return sampleRepository.findAllById(id, pageable)
Url might look like: /samples/id?page=pageNr&size=nrOfElemOnPage
Your repository should return
Page<Sample> findAllById(String id, Pageable pageable)
Also please consider refactoring(indention) the code before posting it to stackoverflow
Also this might be a duplicate: Using findAll PagingAndSortingRepository with filter

QuerydslPredicate with PagingAndSortingRepository

I am new to learning QueryDslPredicate and PagingAndSortingRepository
I want to use use the predicate along with sorting and pagination in my findAll request. How can this be done ?
QTestOrder qTestOrder = QTestOrder.testOrder;
BooleanExpression isUser = qTestOrder.user.eq(userDAO.getUserByPhone(Long.parseLong(params.getFirst(Constant.USER))));
BooleanExpression isId = qTestOrder.id.eq(new Long(params.getFirst(Constant.ID)));
BooleanExpression isStatus = qTestOrder.testStatus.eq(testStatusDAO.getByRank(Integer.parseInt(params.getFirst(Constant.STATUS))));
testOrderRepo.findAll(isUser.or(isId).or(isStatus),qTestOrder.orderCreationTime.desc());
So above returns me list of testOrders, I now want to do pagination over the, using query like below . How do I return all paginated and sorted users based on my query. Is there any method for that or workaround ?
Pageable page = new PageRequest(p, Constant.DEFAULT_PAGE_SIZE);
Page<TestOrder> l = testOrderRepo.findAll(page);
You can implement QueryDslPredicateExecutor<T> in your repository interfaces. This interface provides a method with following signature:
Page<T> findAll(Predicate predicate, Pageable pageable);
Which Returns a page of entities matching the given Predicate.
Suppose you have domain entity, say TestOrder, then you can define a TestOrderRepository like following:
public interface TestOrderRepository extends QueryDslPredicateExecutor<TestOrder> {}
and finally you can:
Pageable pagable = new QPageRequest(1, 10, your_order_specifier)
testOrderRepository.findAll(isUser.or(isId).or(isStatus), pageable);

Resources