スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

Spring MVC ページング機能を実装する(DBアクセス編)

今回は、検索一覧画面にページング機能を追加してみたいと思う。

ページング機能の追加にあたり、jQueryのプラグインであるjqGridを使うことも検討したが、既存の検索一覧を活用したかったので、(今どきではないかもしれないが)サーバー側で実装することにした。実装にあたっては、すべて自前で用意するのではなく、spring-data-commons-1.7.2.RELEASE.jarのorg.springframework.data.domainパッケージ配下で定義されているクラス(Page,Pageable等)を使ってみたいと思う。

今回、ボリュームが多いため、記事を3回に分けて掲載する。
 ①DBアクセス編
  ⇒本記事
 ②コントローラ編
  ⇒次回掲載予定
 ③JSP編
  ⇒次々回掲載予定

◎動作検証にあたっての各バージョンは以下の通り
  • SpringFramework 3.2.8.RELEASE
  • Java 1.7
  • Tomcat 7.0

まずはイメージを掴むため、ページング機能実装前後の画面を掲載しておく。

検索一覧(変更前)
ADMIN_TOP.png

検索一覧(完成イメージ)
ページング_1

なお、スペースの関係上、1ページあたり2レコード表示としている。

1.Book情報

CREATE TABLE Book (
book_id BIGINT PRIMARY KEY AUTO_INCREMENT,
book_name VARCHAR(50) NOT NULL,
price INTEGER,
cover BLOB
);

INSERT INTO Book (book_name,price) VALUES ('Spring DI Sample',1000);
INSERT INTO Book (book_name,price) VALUES ('Spring AOP Sample',2000);
INSERT INTO Book (book_name,price) VALUES ('Spring DATA Sample',3000);
INSERT INTO Book (book_name,price) VALUES ('Spring DATA Tutorial',4000);
INSERT INTO Book (book_name,price) VALUES ('Spring DATA Tutorial2',5000);

動作確認用に5レコード用意している。(最大3ページの想定)

2.BookDao.java(関連箇所のみ掲載)

package jp.co.sample.book.dao;

import java.util.List;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

public interface BookDao<T> {

Page<T> findPageByNameLike(Pageable pageable,String name);
//他のメソッド定義は省略
}

Page、Pageableインターフェースについては、下図を参考にしてほしい。次回のコントローラ編で紹介するが、メソッド名から何をしているのかだいたい見当がつくのではないかと思う。もうひとつの引数「name」については、検索条件のタイトルとなる。あわせて、org.springframework.data.domainパッケージ配下のクラスについても下図を参考にしてほしい。

■参考(Page,Pageableで定義されているメソッド)
Page.png
■参考(org.springframework.data.domainパッケージ配下)
Page2.png

3.BookDaoImpl.java(関連箇所のみ掲載)

package jp.co.sample.book.dao;

import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import jp.co.sample.book.entity.BookEntity;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

@Repository
@Transactional
public class BookDaoImpl implements BookDao<BookEntity> {

private static Logger logger = LoggerFactory.getLogger(BookDaoImpl.class);

@PersistenceContext
private EntityManager manager;

@Override
@Transactional(readOnly=true)
public List<BookEntity> findByNameLike(String name) {
logger.info("findByNameLike start");
Query query = manager.createQuery("from BookEntity where bookName like '%" + name + "%'");
return query.getResultList();
}

@Override
@Transactional(readOnly=true)
public Page<BookEntity> findPageByNameLike(Pageable pageable,String name) {
logger.info("findPageByNameLike start");
Query query = manager.createQuery("from BookEntity where bookName like '%" + name + "%'");
int total = query.getResultList().size();
List<BookEntity> list = query.setFirstResult(pageable.getOffset()).setMaxResults(pageable.getPageSize()).getResultList();
Page<BookEntity> pageList = new PageImpl(list,pagaeble,total);
return pageList;
}
//他のメソッドは省略
}

DAOの実装クラスとなる。上のfindByNameLikeが今まで使用していたタイトルによる検索メソッドで、下のfindPageByNameLikeメソッドが今回追加するメソッドとなり、今後はこちらを使用することになる。
さて、どうしたらPageオブジェクトを返却できるのか、先に掲載したorg.springframework.data.domainパッケージ配下を見ると、PageImplクラスがあることに気付く。クラス名より推測できる通り、PageImplクラスはPageインターフェースを実装しており、こちらのコンストラクタを呼べば、Pageオブジェクトを返せそうだ。
42行目のコンストラクタに必要な引数であるが、第1引数が該当ページに表示するレコードのリスト、第2引数がPageableオブジェクト、第3引数が全ページ分のレコード数となる。40行目が第3引数の全ページ分のレコード数、41行目が第1引数の該当ページに表示するレコードのリストを取得している。41行目について説明しておくと、SQLではoffset、limitを使って、開始位置と取得レコード数を指定するが、JPQLでは、QueryクラスのsetFirstResult(offsetに相当)、setMaxResults(limitに相当)メソッドを使用する。それぞれの引数にはPagebleインターフェースの.getOffset、getPageSizeメソッドを使って値を設定している。ちなみにPageableインターフェースの実装クラスについては、次回のコントローラ編で紹介する。なお、39行目のJPQLについては過去の記事を参考にしてほしい。

■findByNameLikeメソッドに関する過去の記事
Spring MVC Spring Data JPAを使って検索する

■参考(BookDaoPagingRepository.java)

package jp.co.sample.book.dao;

import jp.co.sample.book.entity.BookEntity;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface BookDaoPagingRepository extends PagingAndSortingRepository<BookEntity, Long> {

}

PagingAndSortingRepositoryインターフェースには、「Page findAll(Pageable pageable);」のメソッドが定義されており、こちらのリポジトリを使えば、実装クラスを用意する必要がない。リポジトリについては過去の記事を参考にしてほしい。
今回は、すでにDAOインターフェースを用意してアプリケーションを構築していた経緯と、タイトルで検索する条件が必要だったため、PagingAndSortingRepositoryインターフェースの使用を見送った。

■リポジトリに関する過去の記事
Spring MVC Spring Data JPAを使ってみる(その2)


4.BookService.java(関連箇所のみ掲載)

package jp.co.sample.book.service;

import java.util.List;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

public interface BookService<T> {

Page<T> findPageByNameLike(Pageable pageable,String name);
//他のメソッドは省略
}


5.BookServiceImpl.java(関連箇所のみ掲載)

package jp.co.sample.book.service;

import java.util.List;
import jp.co.sample.book.dao.BookDao;
import jp.co.sample.book.entity.BookEntity;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

@Service
public class BookServiceImpl implements BookService<BookEntity> {

@Autowired
BookDao<BookEntity> dao;

@Override
public Page<BookEntity> findAllPage(Pageable pageable,String name) {
return dao.findPageByNameLike(pageable,name);
}
//他のメソッドは省略
}

Serviceについては、DAOに処理を委譲しているだけとなっている。

今回はここまで。次回に続く。

■過去のSpring関連記事
Spring関連記事 Index

スポンサーサイト

コメントの投稿

非公開コメント

プロフィール

bookmount8

Author:bookmount8
システムエンジニア。サーバーサイドでjavaを扱うことが多い。最近は、ミドルやフロント周りも関心あり。

最新記事
カテゴリ
検索フォーム
最新コメント
月別アーカイブ
これまでの訪問者数
ブロとも申請フォーム

この人とブロともになる

RSSリンクの表示
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。