web-dev-qa-db-ja.com

休止状態のスプリングブートでページネーションを実装する方法

休止状態でスプリングブートを使用しており、プロジェクトでページネーションを使用したい。私はグーグルで検索し、多くの例を見てきましたが、プロジェクトに実装することはできません。

URLに1を渡すと10の結果が返され、2に渡すと次の10の結果が返されるなどのようになります。

これが私のDaoです

@Transactional
public interface PostDao extends CrudRepository<Post, Long>{

@Query(getAllPostsByRank)
List<Post> getAllPostsByRank();

final String getAllPostsByRank= "from Post order by value DESC";
}

ここに私のController

@RequestMapping("/top")
    @ResponseBody 
     public List<Post> getAllPosts(HttpServletRequest req, HttpServletResponse res) throws ServletException {

List<Post> postobj = postDao.getAllPostsByRank();
return postobj;
}

そして、ここに私のrl:

http://localhost:8888/v1.0/post/top/1

提案してください。

13
Nadeem Ahmed

確認してください。あなたのコントローラー

@RequestMapping("/top/pages/{pageno}")
    @ResponseBody 
     public List<Post> getAllPosts(@PathVariable("pageno") int pageno, HttpServletRequest req, HttpServletResponse res) throws ServletException {

List<Post> postobj = postDao.getAllPostsByRank(new PageRequest(pageno,10));
return postobj;
}

あなたの道

@Transactional
public interface PostDao extends CrudRepository<Post, Long>{

@Query(getAllPostsByRank)
List<Post> getAllPostsByRank(Pageable pageable);

final String getAllPostsByRank= "from Post order by value DESC";
}
8
artle

org.springframework.data.domain.Pageableをコントローラーに直接使用することを検討します。次に、このオブジェクトをJPAレイヤーに渡して、返された結果の数とサイズを処理します。

Pageableを使用することの素晴らしい点は、フロントエンドで前/次のページロジックを形成するために使用できるPageオブジェクトを返すことです。

デフォルトでは、このクラスはurlパラメーター「page」および「size」を使用します。したがって、page = 0&size = 10は最初の10個のアイテムを返します。

したがって、あなたの場合、コードは次のようになります。

@ResponseBody
@RequestMapping("/top/pages/")
public List<Post> getAllPosts(@PageableDefault(value=10, page=0) Pageable pageable) throws ServletException {
    Page page = postDao.findAll(pageable);
    return page.getContent();
}

注釈@PageableDefaultはデフォルトを設定するためのものであり、必須ではありません。

フロントエンドでは、次のページ呼び出しは<a href="/top/pages?page=1">Next</a>になります。これにより、11から20までの投稿のリストが返されます。

22
Ithar

Spring Bootでページネーションを実装するのは、基本的な手順に従うだけで非常に簡単です-

1-リポジトリインターフェイスのPagingAndSortingRepositoryを拡張します

public interface UserRepository extends PagingAndSortingRepository <User, Long> 

2-メソッド宣言は次の例のようにする必要があります

Page<User> userList(Pageable pageable);

3-Serviceクラスのメソッド実装は、次の例のようになります

@Override
public Page<User> userList(Pageable pageable) {
        return userRepository.findAll(pageable);
}

4-コントローラークラスコードは次のようになります

@GetMapping("/list")
public String userList(Model model, Pageable pageable) {
        Page<User> pages = userService.userList(pageable);
        model.addAttribute("number", pages.getNumber());
        model.addAttribute("totalPages", pages.getTotalPages());
        model.addAttribute("totalElements",       
                                      pages.getTotalElements());
        model.addAttribute("size", pages.getSize());
        model.addAttribute("users", pages.getContent());
        return "/user/list";
}

フロントエンドからの呼び出しは次のようになります

http://localhost:8080/application/user/list?page=0&size=5
http://localhost:8080/application/user/list?page=1&size=5
http://localhost:8080/application/user/list?page=2&size=5

詳細については、以下のビデオをご覧ください

スプリングブート:ページネーションの基本

スプリングブート:ページネーションアドバンス

読んでくれてありがとう

9

ネイティブクエリを使用した動的ページネーションの実装方法

ここで、リポジトリおよびサービスレイヤーとデータ転送オブジェクト(DTO)を見つけることができます。これらは、結果のマッピングとコントローラーレイヤーへの送信に使用されます。

public interface CustomSomethingRepository {
    List<Something> findPagedResultBySomethingElseId(long somethingElseId, int offset, int limit);
}

public class SomethingRepositoryImpl implements CustomSomethingRepository {
    @Autowired
    private EntityManager em;

    @SuppressWarnings("unchecked")
    @Override
    public List<Something> findPagedResultBySomethingElseId(long somethingElseId, int offset, int limit) {
        String query = "select s.* from Something s "
                + "join somethingelse selse on selse.id = s.fk_somethingelse "
                + "where selse.id = :somethingElseId "
                + "order by selse.date";
        Query nativeQuery = em.createNativeQuery(query);
        nativeQuery.setParameter("somethingElseId", somethingElseId);
        //Paginering
        nativeQuery.setFirstResult(offset);
        nativeQuery.setMaxResults(limit);
        final List<Object[]> resultList = nativeQuery.getResultList();
        List<Something> somethingList = Lists.newArrayList();
        resultList.forEach(object -> somethingList.add(//map obj to something));
        return somethingList;
    }
}

Hibernateはクエリを次のように変換します:

SELECT inner_query.*, ROW_NUMBER() OVER (ORDER BY CURRENT_TIMESTAMP) as __hibernate_row_nr__ FROM ( select TOP(?) t as page0_ from Something s join s.somethingelse as selse order by selse.date ) inner_query ) SELECT page0_ FROM query WHERE __hibernate_row_nr__ >= ? AND __hibernate_row_nr__ < ?


@Service
public class SomethingService {
    private SomethingRepository somethingRepository;
    @Autowired
    public SomethingService(SomethingRepository somethingRepository){
        this.somethingRepository = somethingRepository;
    }
    @Transactional(readOnly=true)
    public PageDto getSomething(long somethingElseId, int page, int size){
         List<Something> somethings = somethingRepository.findBySomethingElseId(somethingElseId, offset, limit);
        return new PagedResult<>(somethings
                .stream()
                .map(SomethingDto::createDto)
                .sorted(comparing(SomethingDto::getDatum))
                .collect(toList()), somethings.getTotalElements(), somethings.getTotalPages();
    }
}
@Controller
//....
public class PagedResult<T> {
    public static final long DEFAULT_OFFSET = 0;
    public static final int DEFAULT_MAX_NO_OF_ROWS = 100;
    private int offset;
    private int limit;
    private long totalElements;
    private List<T> elements;
    public PagedResult(List<T> elements, long totalElements, int offset, int limit) {
        this.elements = elements;
        this.totalElements = totalElements;
        this.offset = offset;
        this.limit = limit;
    }
    public boolean hasMore() {
        return totalElements > offset + limit;
    }
    public boolean hasPrevious() {
        return offset > 0 && totalElements > 0;
    }
    public long getTotalElements() {
        return totalElements;
    }
    public int  getOffset() {
        return offset;
    }
    public int getLimit() {
        return limit;
    }
    public List<T> getElements() {
        return elements;
    }
}

長所と短所長所:Spring Dataを使用した場合と比較して、生成されるSQLクエリが少なくなります。これらの複雑なクエリはSpring Dataで記述できないため、クエリをネイティブクエリとして指定する必要がありますが、この方法論を使用してクエリをページングできます。

短所:「オブジェクト」配列は、Javaオブジェクトにマッピングする必要があります。これは苦痛であり、保守が困難です。

Spring DataでOffsetLimitページネーションを実装する方法私の知る限り、デフォルトのSpring Dataリポジトリで必要なものに対する「すぐに使える」サポートはありません。ただし、制限/オフセットパラメータを取るページング可能オブジェクトのカスタム実装を作成できます。

ページング可能なオブジェクトを作成し、それをPaginationAndSortingRepositoryに渡します。

public class OffsetLimitRequest implements Pageable {
    private int limit;
    private int offset;
    public OffsetLimitRequest(int offset, int limit){
        this.limit = limit;
        this.offset = offset;
    }
        @Override
    public int getPageNumber() {
        return 0;
    }
    @Override
    public int getPageSize() {
        return limit;
    }
    @Override
    public int getOffset() {
        return offset;
    }
    ....
}

これは、リポジトリ層を変更する必要がないことを意味します。必要な変更は、次のようにサービス層に加えることだけです。

@Service
public class SomethingService {
    private SomethingRepository somethingRepository;
    @Autowired
    public SomethingService(SomethingRepository somethingRepository){
        this.somethingRepository = somethingRepository;
    }
    @Transactional(readOnly=true)
    public PageDto getSomething(long somethingElseId, int page, int size){
        Page<Something> somethings = somethingRepository.findBySomethingElseId(somethingElseId, new OffsetLimitRequest(offset, limit));
        return new PageDto(somethings.getContent()
                .stream()
                .map(SomethingDto::createDto)
                .sorted(comparing(SomethingDto::getDatum))
                .collect(toList()), somethings.getTotalElements(), somethings.getTotalPages();
    }
}

結果を手動でマッピングする必要はなく、開発からかなりの時間がかかることに注意してください。