10

I have tried implementing JPA Repository with Spring Boot it works fine. Now if i try to implement custom query in interface which extends JpaRepository using @Query Annotation it works fine returns List of beans.(using NamedQuery). Now when i try to use pagination for custom method/query it doesn't work.

Code :

Controller :

@RequestMapping("/custompages/{pageNumber}")
public String getAllEmployeesUsingNamedQueryWithPaging(@PathVariable Integer pageNumber,Model model)
{
    Page<Employee> page = employeeService.getAllEmployeesUsingNamedQueryWithPaging(pageNumber);

    System.out.println("current page "+page);
    System.out.println("current page content"+page.getContent());

     int current = page.getNumber() + 1;
    int begin = Math.max(1, current - 5);
    int end = Math.min(begin + 10, page.getTotalPages());

    model.addAttribute("empList", page.getContent());
    model.addAttribute("empPages", page);
    model.addAttribute("beginIndex", begin);
    model.addAttribute("endIndex", end);
    model.addAttribute("currentIndex", current);

    return "employeeWorkbench";
}

Service

@Override
public Page<Employee> getAllEmployeesUsingNamedQueryWithPaging(Integer  
pageNumber) {

    PageRequest pageRequest =
            new PageRequest(pageNumber - 1, PAGE_SIZE, 
    Sort.Direction.ASC, "id");
    return   
employeeDao.getAllEmployeesUsingNamedQueryWithPaging(pageRequest);
}

Dao

@Transactional
public interface EmployeeDao  extends JpaRepository<Employee, Long>{

@Query(name="HQL_GET_ALL_EMPLOYEE_BY_ID")//Works Fine
public List<Employee> getEmpByIdUsingNamedQuery(@Param("empId") Long
empId);     

@Query(name="HQL_GET_ALL_EMPLOYEE") //throws exception
public Page<Employee> getAllEmployeesUsingNamedQueryWithPaging(Pageable     
pageable);  
}

NamedQuery

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 
3.0//EN"  
"http://hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping>

<query name="HQL_GET_ALL_EMPLOYEE">from Employee</query>

<query name="HQL_GET_ALL_EMPLOYEE_BY_ID">from Employee where id = 
:empId</query>

</hibernate-mapping>

Exception : java.lang.IllegalArgumentException: Type specified for TypedQuery [java.lang.Long] is incompatible with query return type [class com.mobicule.SpringBootJPADemo.beans.Employee]

I just want to have pagination functionality provided by Spring JPA Repository for custom methods and query also. How can I achieve this?

xenoterracide
  • 16,274
  • 24
  • 118
  • 243
ashish
  • 161
  • 1
  • 6
  • 13
  • if instead of using a named query in xml, you put the query directly in the `@Query("from Employee")` does it change the behavior? also the @Transactional on the repository is redundant. Also for queries this simple you'd be better off just using the `findAll` the repository already has. – xenoterracide Aug 06 '15 at 14:30
  • also the error is implying that for some reason (not obvious to me) it thinks that the query specified should return a Long and not Employees – xenoterracide Aug 06 '15 at 14:40
  • @xenoterracide : Thanks for response. I tried with simply @Query("from Employee") but this will return me List and NOT Page. My motive is to use JpaRepositories build in Paging Functionality For my custom queries also. And as you said i used findAll this works fine with no issues even works well with pagination also.but i want to have same functionality for my custom queries also. – ashish Aug 06 '15 at 14:55
  • I have searched for this query i got know that when JpaRepository executes its method findAll,findBy......etc with paging it runs 2 queries ---one for count and other for actual data. – ashish Aug 06 '15 at 15:01
  • yes that count is intentional... so it knows how many pages it has. If you have the return type specified as `Page` you should not get a List, you should only get a List if you ask for a List or a sub interface of List (such as Iterable) – xenoterracide Aug 06 '15 at 15:07
  • @xenoterracide : i am not expecting List i want Page only. because i want pagination – ashish Aug 06 '15 at 15:21

1 Answers1

12

I'm not sure why, but for some reason simply doing from Entity causes the "id" to be returned, instead you need to provide the entity returned in the select, like select f from Foo f

public interface FooRepo extends PagingAndSortingRepository<Foo, Long> {

@Query( "select f from Foo f" )
Page<Foo> findAllCustom( Pageable pageable );

Page<Foo> findAllByBarBazContaining( String baz, Pageable pageable );
}

I received the same error, with just from Foo. I also believe you can reference these by name to the xml file as you were. here's my full code

further testing says that from Foo f also works, I do not know why the alias is required, perhaps it is part of the JPQL spec.

Here is a test showing how to do simple paging, sorting by one property and sorting by multiple properties

@Test
public void testFindAllCustom() throws Exception {
    Page<Foo> allCustom = fooRepo.findAllCustom( pageable );

    assertThat( allCustom.getSize(), is( 2 ) );

    Page<Foo> sortByBazAsc = fooRepo.findAllCustom( new PageRequest( 0, 2, Sort.Direction.ASC, "bar.baz" ) );

    assertThat( sortByBazAsc.iterator().next().getBar().getBaz(), is( "2baz2bfoo" ) );

    Page<Foo> complexSort = fooRepo.findAllCustom( new PageRequest( 0, 2, new Sort(
            new Sort.Order( Sort.Direction.DESC, "bar.baz" ),
            new Sort.Order( Sort.Direction.ASC, "id" )
    ) ) );

    assertThat( complexSort.iterator().next().getBar().getBaz(), is( "baz1" ) );
}
xenoterracide
  • 16,274
  • 24
  • 118
  • 243
  • changing the query worked.Now i am able to have Jpa pagination functionality for Custom Queries as well. Thank !!! Cheers....!!!! – ashish Aug 07 '15 at 07:37
  • you should make this your accepted answer, upvotes are nice too – xenoterracide Aug 07 '15 at 14:45
  • @xenoterracide please look at this.. http://stackoverflow.com/questions/32434058/how-to-implement-pagination-in-spring-boot-with-hibernate – Nadeem Ahmed Sep 07 '15 at 08:31
  • @NadeemAhmed if that works that doesn't really explain what happened here, other than "bug". I've got various working paged specifications and `@Query` as well as the simple method parser. All I can say is, I too get the exception described in the askers post. – xenoterracide Sep 07 '15 at 14:27
  • @NadeemAhmed oh looking at it again that is doing a sort by DESC, mine is allowing for you to change the sort with a PageRequest – xenoterracide Sep 07 '15 at 15:42
  • @NadeemAhmed I've updated this to include examples of dynamic sorting – xenoterracide Sep 07 '15 at 17:09
  • For some very strange reason I have this problem only when I run an integration test with h2db. The query works fine with or without the "select f" part of the "select f from Foo", but only with MySQL. With H2 I got the illegal argument exception. Any help? – senape Nov 13 '19 at 08:52
  • 1
    ok, i found the problem and it's quite weird. the main query is a bit complex, with several inner and left fetch joins. I wrote both the query and the count query as select f from foo...; now, if i run it against mysql, the query works fine. h2db instead, needs "select count(f) from foo" as count query. Hope this would help – senape Nov 13 '19 at 10:17