让我们从支持分页的经典JPA方法开始。 考虑一个简单的域类–一个具有名字,姓氏的“成员”。 为了支持在成员列表上进行分页,JPA方法是支持一种查找器,该查找器将获取第一个结果(firstResult)的偏移量和要检索的结果(maxResults)的大小,方法是:
import java.util.List;import javax.persistence.TypedQuery;import org.springframework.stereotype.Repository;import mvcsample.domain.Member;@Repository
public class JpaMemberDao extends JpaDao<Long, Member> implements MemberDao{public JpaMemberDao(){super(Member.class);}@Overridepublic List<Member> findAll(int firstResult, int maxResults) {TypedQuery<Member> query = this.entityManager.createQuery('select m from Member m', Member.class);return query.setFirstResult(firstResult).setMaxResults(maxResults).getResultList();}@Overridepublic Long countMembers() {TypedQuery<Long> query = this.entityManager.createQuery('select count(m) from Member m', Long.class);return query.getSingleResult();}
}
如上所示,需要一个附加的API返回记录的数量来确定实体列表的页数。 使用此API,通常需要用户界面提供两个参数:
- 当前显示的页面(例如“ page.page”)
- 每页列表的大小(例如“ page.size”)
控制器将负责通过以下方式将这些输入转换为JPA所需的输入– firstResult和maxResults:
@RequestMapping(produces='text/html')
public String list(@RequestParam(defaultValue='1', value='page.page', required=false) Integer page, @RequestParam(defaultValue='10', value='page.size', required=false) Integer size, Model model){int firstResult = (page==null)?0:(page-1) * size;model.addAttribute('members',this.memberDao.findAll(firstResult, size));float nrOfPages = (float)this.memberDao.countMembers()/size;int maxPages = (int)( ((nrOfPages>(int)nrOfPages) || nrOfPages==0.0)?nrOfPages+1:nrOfPages);model.addAttribute('maxPages', maxPages);return 'members/list';
}
给定一个列表作为模型属性和所有页面的数量(上面的maxPages个),可以将该列表转换为jsp中的一个简单表,Spring Roo打包了一个不错的标记库,可用于显示在jsp页面中的分页元素,我已将其包含在参考中。
因此,这是使用JPA和Spring MVC进行分页的方法。 Spring-Data-JPA使这个过程变得更加简单 ,首先是支持检索分页列表的存储库接口–以最简单的形式,该存储库仅需要扩展Spring-Data-JPA接口,并在运行时生成实现真正JPA调用的代理:
import mvcsample.domain.Member;import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;public interface MemberRepository extends JpaRepository<Member, Long>{//
}
鉴于此,访问存储库接口的控制器方法也非常简单:
@RequestMapping(produces='text/html')
public String list(Pageable pageable, Model model){Page<Member> members = this.memberRepository.findAll(pageable);model.addAttribute('members', members.getContent());float nrOfPages = members.getTotalPages();model.addAttribute('maxPages', nrOfPages);return 'members/list';
}
控制器方法接受一个名为Pageable的参数,此参数使用Spring MVC HandlerMethodArgumentResolver填充,该MVC HandlerMethodArgumentResolver通过名称“ page.page”和“ page.size”查找请求参数,并将其转换为Pageable参数。 此自定义HandlerMethodArgumentResolver通过以下方式向Spring MVC注册:
<mvc:annotation-driven><mvc:argument-resolvers><bean class='org.springframework.data.web.PageableArgumentResolver'></bean></mvc:argument-resolvers>
</mvc:annotation-driven>
JpaRepository API接受pageable参数并返回一个页面,在内部自动填充也可以从Page方法检索的页面数。 如果需要显式指定查询,则可以采用多种方法来完成,其中一种方法如下:
@Query(value='select m from Member m', countQuery='select count(m) from Member m')
Page<Member> findMembers(Pageable pageable);
我可以看到的一个问题是,可分页的页面号是0索引,而从UI传递的那个是1索引,但是PageableArgumentResolver在内部处理并将1索引的UI页面参数转换为所需的0索引值。 因此,Spring Data JPA使实现分页列表页面变得非常简单。 我包括一个将所有这些都联系在一起的示例项目,以及使分页列表显示变得简单的分页标签库。
资源:
- 实现分页列表的示例项目位于此处 :https://github.com/bijukunjummen/spring-mvc-test-sample.git
- Spring-Data-JPA参考 :http://static.springsource.org/spring-data/data-jpa/docs/current/reference/html/
参考资料: all和其他博客中的Spring Data JPA和我们的JCG合作伙伴 Biju Kunjummen的分页 。
翻译自: https://www.javacodegeeks.com/2013/01/spring-data-jpa-and-pagination.html