在实际开发场景中,排序与分页查询是必须的,幸运的是Spring Data JPA充分考虑了排序与分页查询的场景,为我们提供Sort类 Page接口 Pageable接口 下面通过一个实战来阐明
1:创建持久化实体类
创建名为com.ch.ch6_4.entity的包 并在该包中创建名为Article和Author的持久化实体类
代码如下
Article
package com.ch.ch6_2.entity; import java.io.Serializable; import javax.persistence.Basic; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.Lob; import javax.persistence.ManyToOne; import javax.persistence.Table; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.Size; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; @Entity @Table(name = "article_table") @JsonIgnoreProperties(value = { "hibernateLazyInitializer"}) public class Article implements Serializable{ private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; //标题 @NotEmpty(message = "标题不能为空") @Size(min = 2, max = 50) @Column(nullable = false, length = 50) private String title; //文章内容 @Lob //大对象,映射 为MySQL的Long文本类型 @Basic(fetch = FetchType.LAZY) @NotEmpty(message = "内容不能为空") @Size(min = 2) @Column(nullable = false) private String content; //所属作者,文章与作者是多对一的关系 @ManyToOne(cascade={CascadeType.MERGE,CascadeType.REFRESH},optional=false) //可选属性optional=false,表示author不能为空。删除文章,不影响用户 @JoinColumn(name="id_author_id")//设置在article表中的关联字段(外键) @JsonIgnore private Author author; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public Author getAuthor() { return author; } public void setAuthor(Author author) { this.author = author; } }
Author
package com.ch.ch6_2.entity; import java.io.Serializable; import java.util.List; import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.OneToMany; import javax.persistence.Table; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; @Entity @Table(name = "author_table") @JsonIgnoreProperties(value = { "hibernateLazyInitializer"}) public class Author implements Serializable{ private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; //作者名 private String aname; //文章列表,作者与文章是一对多的关系 @OneToMany( mappedBy = "author", cascade=CascadeType.ALL, targetEntity = Article.class, fetch=FetchType.LAZY ) private List<Article> articleList; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getAname() { return aname; } public void setAname(String aname) { this.aname = aname; } public List<Article> getArticleList() { return articleList; } public void setArticleList(List<Article> articleList) { this.articleList = articleList; } }
2:创建数据访问层
创建名为com.ch.ch6_4repository的包 并在该包中创建名为AuthorRepository的接口
package com.ch.ch6_2.repository; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import com.ch.ch6_2.entity.Author; public interface AuthorRepository extends JpaRepository<Author, Integer>{ /** * 根据文章标题包含的内容,查询作者(关联查询) * 相当于JPQL语句:select a from Author a inner join a.articleList t where t.title like %?1% */ public Author findByArticleList_titleContaining(String title); /** * 根据文章标题包含的内容,查询作者(关联查询) */ @Query("select a from Author a inner join a.articleList t where t.title like %?1%" ) public Author findAuthorByArticleListtitleContaining(String title); }
3:创建业务层
创建名为com.ch.ch6_4.service的包 并在该包中创建名为ArticleAndAuthorService的接口和接口实现类ArticleAndAuthorServiceImpl
接口
package com.ch.ch6_2.service; import java.util.List; import com.ch.ch6_2.entity.Article; import com.ch.ch6_2.entity.Author; public interface AuthorAndArticleService { public void saveAll(); public List<Article> findByAuthor_id(Integer id); public List<Article> findByAuthor_aname(String aname); public Author findByArticleList_titleContaining(String title); public Author findAuthorByArticleListtitleContaining(String title); }
接口实现类
package com.ch.ch6_2.service; import java.util.ArrayList; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.ch.ch6_2.entity.Article; import com.ch.ch6_2.entity.Author; import com.ch.ch6_2.repository.ArticleRepository; import com.ch.ch6_2.repository.AuthorRepository; @Service public class AuthorAndArticleServiceImpl implements AuthorAndArticleService{ @Autowired private AuthorRepository authorRepository; @Autowired private ArticleRepository articleRepository; @Override public void saveAll() { //保存作者(先保存一的一端) Author a1 = new Author(); a1.setAname("陈恒1"); Author a2 = new Author(); a2.setAname("陈恒2"); ArrayList<Author> allAuthor = new ArrayList<Author>(); allAuthor.add(a1); allAuthor.add(a2); authorRepository.saveAll(allAuthor); //保存文章 Article at1 = new Article(); at1.setTitle("JPA的一对多111"); at1.setContent("其实一对多映射关系很常见111。"); //设置关系 at1.setAuthor(a1); Article at2 = new Article(); at2.setTitle("JPA的一对多222"); at2.setContent("其实一对多映射关系很常见222。"); //设置关系 at2.setAuthor(a1);//文章2与文章1作者相同 Article at3 = new Article(); at3.setTitle("JPA的一对多333"); at3.setContent("其实一对多映射关系很常见333。"); //设置关系 at3.setAuthor(a2); Article at4 = new Article(); at4.setTitle("JPA的一对多444"); at4.setContent("其实一对多映射关系很常见444。"); //设置关系 at4.setAuthor(a2);//文章3与文章4作者相同 ArrayList<Article> allAt = new ArrayList<Article>(); allAt.add(at1); allAt.add(at2); allAt.add(at3); allAt.add(at4); a public Author findByArticleList_titleContaining(String title) { return authorRepository.findByArticleList_titleContaining(title); } @Override public Author findAuthorByArticleListtitleContaining(String title) { return authorRepository.findAuthorByArticleListtitleContaining(title); } }
4:创建控制器类
创建名为com.ch,ch6_4.controller的包 并在该包中创建名为TestSortAndPage的控制器类
package com.ch.ch6_4.controller; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import com.ch.ch6_4.entity.Author; import com.ch.ch6_4.service.ArticleAndAuthorService; @Controller public class TestSortAndPage { @Autowired private ArticleAndAuthorService articleAndAuthorService; @RequestMapping("/findByAnameContaining") @ResponseBody public List<Author> findByAnameContaining(String aname, String sortColum){ return articleAndAuthorService.findByAnameContaining(aname, sortColum); } @RequestMapping("/findAllAuthorByPage") /** * @param page第几页 */ public String findAllAuthorByPage(Integer page, Model model){ return articleAndAuthorService.findAllAuthorByPage(page, model); } }
5:创建View视图页面
创建index.html页面 部分代码如下
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>显示分页查询结果</title> <link rel="stylesheet" th:href="@{css/bootstrap.min.css}" /> <link rel="stylesheet" th:href="@{css/bootstrap-theme.min.css}" /> </head> <body> <div class="panel panel-primary"> <div class="panel-heading"> <h3 class="panel-title">Spring Data JPA分页查询</h3> </div> </tr> <tr> <td colspan="2" align="right"> <ul class="pagination"> <li><a>第<span th:text="${page}"></span>页</a></li> <li><a>共<span th:text="${totalPage}"></span>页</a></li> <li><a>共<span th:text="${totalCount}"></span>条</a></li> <li> <a th:href="@{findAllAuthorByPage(page=${page-1})}" th:if="${page != 1}">上一页</a> </li> <li><a th:href="@{findAllAuthorByPage(page=${page+1})}" th:if="${page != totalPage}">下一页</a> </li> </ul> </td> </tr> </tbody> </table> </div> </div> </div> </div> </body> </html>
6:运行主类 效果如下