42

I am retrieving data by CrudRepository in Spring Data JPA. I want to filter my records those are retrieved from my custom query provided in @Query annotation. I tried .setMaxResults(20); for select rows.. But it gives errors. I want to filter first 20 rows from my table

this is my repository

package lk.slsi.repository;

import java.util.Date;
import lk.slsi.domain.SLSNotification;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;

import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;

/**
 * Created by ignotus on 2/10/2017.
 */
public interface SLSNotificationRepository extends CrudRepository<SLSNotification, Integer> {


    @Override
    SLSNotification save(SLSNotification slsNotification);

    @Override
    SLSNotification findOne(Integer snumber);

    @Override
    long count();

    @Override
    void delete(Integer integer);

    @Override
    void delete(SLSNotification slsNotification);

    @Override
    void delete(Iterable<? extends SLSNotification> iterable);

    @Override
    List<SLSNotification> findAll();

    @Query("select a from SLSNotification a where a.slsiUnit in :unitList order by snumber desc")
    List<SLSNotification> getApplicationsByUnit(@Param("unitList") List<String> unitList);

    @Query("select a from SLSNotification a where a.userId = :userId")
    List<SLSNotification> getApplicationsByUserId(@Param("userId") String userId);

    @Query("select a.snumber, a.date, a.slsNo, a.slsiUnit, a.productDesc, a.status from SLSNotification a where a.userId = :userId ORDER BY snumber desc")
    List<SLSNotification> getApplicationsByUserIdforManage(@Param("userId") String userId);

    @Query("select a from SLSNotification a where a.slsNo = :slsNo")
    SLSNotification getApplicationBySLSNumber(@Param("slsNo") String slsNo);

}

I want my List<SLSNotification> getApplicationsByUserIdforManage(@Param("userId") String userId); method to retrieve a limited set of data. How can I call entity manager or something or anything to do this ?

Please help me doing this. output img

Nipun Vidarshana
  • 451
  • 1
  • 5
  • 12

5 Answers5

72

You can provide limitations by limitstatement in your SQL. And have nativeQuery = true in @Query annotation to set JPA provider(like Hibernate) to consider this as a native SQL query.

@Query(nativeQuery = true, value = "SELECT * FROM SLSNotification s WHERE s.userId = :userId ORDER BY snumber DESC LIMIT 20")
List<SLSNotification> getUserIdforManage(@Param("userId") String userId);

Or

Additionally if you want to exploit the handy features from Spring Data JPA, you can do it by proper method naming

List<SLSNotification> findByUserIdOrderBySNumber(@Param("userId") String userId, Pageable pageable);

If you dont know already, Spring Data JPA constructs Query from the method names. Amazing, right? Read this documentation for better understanding.

Now just call this method like

Pageable topTwenty = PageRequest.of(0, 20);
List<SLSNotification> notifications = repository.findByUserIdOrderBySNumber("101", topTwenty);

Besides, If you are using Java 8

You have option for having default method in interface and make life a bit easier

 List<SLSNotification> findByUserIdOrderBySNumber(@Param("userId") String userId, Pageable pageable);

 default List<User> findTop20ByUserIdOrderBySNumber(String userId) {
    return findByUserIdOrderBySNumber(userId, PageRequest.of(0,20));
 }
Shafin Mahmud
  • 3,831
  • 1
  • 23
  • 35
  • Ok i wil do that.....thank you for your comment...Please wait till i check – Nipun Vidarshana Dec 03 '17 at 08:30
  • I added but limit is not working..It returns still my previous query and doesn't allow desc order – Nipun Vidarshana Dec 03 '17 at 08:40
  • 1
    `limit` is a SQL statement. It obviously work in workbench – Shafin Mahmud Dec 03 '17 at 08:43
  • could you give the stacktrace of your exception ? – Shafin Mahmud Dec 03 '17 at 08:44
  • there were not output in console or jsp.. But i aspected is not became – Nipun Vidarshana Dec 03 '17 at 08:48
  • If there is no exception, that means it returns you data ?? – Shafin Mahmud Dec 03 '17 at 08:50
  • @ Shafin Mahmud check theimage.. I want to add desc order in entry number and limit to 1... – Nipun Vidarshana Dec 03 '17 at 09:05
  • tell me one thing. Does your application return same output for the query I mentioned ? – Shafin Mahmud Dec 03 '17 at 09:22
  • yes..It is not filtered data... this methord is use for select data – Nipun Vidarshana Dec 03 '17 at 09:25
  • Did you check the log for generated sql that hibernate is running ? if not enable `show_sql: true` from your hibernate configuration – Shafin Mahmud Dec 03 '17 at 09:31
  • I requested the query from the ajax.therefore the quary execution not display in the console – Nipun Vidarshana Dec 03 '17 at 09:59
  • where are you running this `interface` then ? Where did you call your `getApplicationsByUserIdforManage()` ?? :O – Shafin Mahmud Dec 03 '17 at 10:08
  • Hibernate: select slsnotific0_.snumber as snumber1_6_, slsnotific0_.acc_rep as acc_rep2_6_, slsnotific0_.acc_rep_loc as acc_rep_3_6_, slsnotific0_.app_postdate as app_post4_6_, slsnotific0_.bl_date as bl_date5_6_, slsnotific0_.bl_loc as bl_loc6_6_, slsnotific0_.bl_no as bl_no7_6_.cus_date as cus_dat10_6_, slsnotific0,.total_qty as total_q40_6_, slsnotific0_.trading_country as trading41_6_, slsnotific0_.uom as uom42_6_, slsnotific0_.user_id as user_id43_6_, slsnotific0_.vessel as vessel44_6_ from sls_notifications slsnotific0_ where slsnotific0_.user_id=? – Nipun Vidarshana Dec 03 '17 at 10:10
  • the console view this msg as a query – Nipun Vidarshana Dec 03 '17 at 10:10
  • okay. this depicts your hibernate is not running the query you are providing. – Shafin Mahmud Dec 03 '17 at 10:13
  • could you mention your `Spring Data JPA` version ? – Shafin Mahmud Dec 03 '17 at 10:17
  • Yeah..Success..Thank you sir...Error is in my workbench table....column name missmath – Nipun Vidarshana Dec 03 '17 at 10:32
  • sir i have a small question ...if u can tell the methord to do that https://stackoverflow.com/questions/47614685/how-to-store-post-methord-data-in-javascript-varible?noredirect=1#comment82192780_47614685 – Nipun Vidarshana Dec 03 '17 at 10:34
  • please help me to do that – Nipun Vidarshana Dec 03 '17 at 10:35
  • 1
    okay. good to hear. But there are more other ways to do this same thing. stay tune. I am updating the answer. – Shafin Mahmud Dec 03 '17 at 10:35
  • Nice. But if this helps you, consider to accept and upvote this answer, so that others can find it helpful too. – Shafin Mahmud Dec 03 '17 at 10:53
  • i have another error in this quary.I want to add a limit by jsp using pathvariable.So when i write a cord it gives error when compile... this is the cord @Query(value = "select * from SLSNotification s where s.user_Id = :userId ORDER BY snumber DESC limit :limit", nativeQuery = true) List getApplicationsByUserIdforManage(@Param("userId") String userId,@Param("limit") String limit); – Nipun Vidarshana Dec 03 '17 at 11:28
  • You just mentioned your query. But whats the error ? When does it occur ? And if you want to bind a variable from your user request thats something to do from the `Controller`s. – Shafin Mahmud Dec 03 '17 at 13:31
  • i can do it from controller..but when i do it from controller it get more mb usage..when rows has 500000 it destroy huge data..so i use ajax..it is simple and use low data.so can i do it from ajax – Nipun Vidarshana Dec 03 '17 at 13:48
  • what ever you do, it must to go through your Controller or Servlet that handlers `HttpRequest` (when you are using `Spring MVC`). And in fact each of your Ajax sends request to your controller. – Shafin Mahmud Dec 03 '17 at 13:58
  • And incase of handling huge amount of data you might want to use pagination for your view layer. And send request to server to provide paged data. – Shafin Mahmud Dec 03 '17 at 14:00
  • I do it..I dont't want that..I want from ajax – Nipun Vidarshana Dec 03 '17 at 16:31
  • So many options, but none refers to what op asks - how to limit number of results in non-native `@Query`. – ACV Jul 05 '23 at 19:35
4

As per the feature provided by Spring Data JPA to create queries via method names you can use this. For more Supported query method predicate keywords and modifiers check this.

Optional<List<SLSNotification>> findTop20ByUserId(String id); 

or

Optional<List<SLSNotification>> findFirst20ByUserId(String id); 

This will limit the query results to the first of results.

If you want to limit the ordered result set then use Desc, Asc with OrderBy in the method names as below.

// return the first 20 records which are ordered by SNumber. If you want Asc order, no need to add that keyword since it is the default of `OrderBy` 
Optional<List<SLSNotification>> findFirst20ByUserIdOrderBySNumberDesc(String id);  

Suggestion -- It is better and safe from code side to use return type of the Optional in queries like find, get where there is doubt of having at least single result.

DevThiman
  • 920
  • 1
  • 9
  • 24
1

I found that LIMIT can only be used with the nativeQuery which can be used in some cases.

Ideally the query method name can be used like:

EntityA findTopByParamXAndParamYAndParamZOrderByIdDesc();

and it will restrict the resut to one entity (one record)

In my case as I have a inner join, I cannot really use the method naming and I would also avoid to use the Paging as it delegate the logic to the caller.

I found this quite elegant solution using the MAX(a) in the query:

@Query(value = "SELECT MAX(a) FROM EntityA a " +
        "INNER JOIN EntityB b on a.Bid = b.id " +
        "WHERE b.paramY = :paramY " +
        "AND b.paramZ = :paramZ " +
        "AND a.paramX = :paramX " +
        "ORDER BY a.id DESC")
EntityA findLastEntityAByParamsXYZ(
        @Param("paramX") String paramX,
        @Param("paramY") String paramY,
        @Param("paramZ") String paramZ);
рüффп
  • 5,172
  • 34
  • 67
  • 113
0

If you do not want to define the limit hard coded in the repository method name, you could use Page e Pageable in the service that calls the repository:

Page<Passenger> page = repository.findAll(
  PageRequest.of(0, 20, Sort.by(Sort.Direction.ASC, "seatNumber")));

More examples at: https://www.baeldung.com/jpa-limit-query-results

NaN
  • 8,596
  • 20
  • 79
  • 153
0
public interface ICategoriaDao extends CrudRepository<Categoria, Long>{

    @Query(value="select * from categoria c order by nombre limit ?1 offset ?2", nativeQuery=true)
    public List<Categoria> findPagina(Integer limit,  Integer offset );
}
Javi
  • 111
  • 2
  • Remember that Stack Overflow isn't just intended to solve the immediate problem, but also to help future readers find solutions to similar problems, which requires understanding the underlying code. This is especially important for members of our community who are beginners, and not familiar with the syntax. Given that, **can you [edit] your answer to include an explanation of what you're doing** and why you believe it is the best approach? – Jeremy Caney Nov 18 '22 at 00:39