Spring Data JPA 實現多表關聯查詢

言曌發表於2018-04-02

最近抽出時間來做部落格,資料庫操作使用的是 JPA,相對比 Mybatis 而言,JPA 單表操作非常方便,增刪改查都已經寫好了。但是多表操作就不如 Mybatis 那種直接寫 sql 語句來得方便,JPA 的多表操作比較麻煩。

 

需求描述

獲得文章列表,文章列表裡需要顯示每篇文章的分類目錄列表,因為一個文章可能有多個分類,一個分類當然也可以對應多篇文章的。

 

下面是我用截圖軟體畫的一個圖,描述的是三張表和其主要欄位。

Spring Data JPA 實現多表關聯查詢

 

文章表 article 和分類表 category 通過 中間表 article_category 關聯

 

我們的需求也很簡單,從資料庫裡查詢所有文章,並給每篇文章加一個分類列表的屬性。

如影像這樣

Spring Data JPA 實現多表關聯查詢

 

程式碼實現

Spring Data JPA 需要的依賴和配置檔案這裡就不給出了,因為不是本文的重點。

 

實體類

1、實體類 Article.java

  1. package com.liuyanzhao.blog.entity;
  2. import javax.persistence.*;
  3. import java.io.Serializable;
  4. import java.util.Date;
  5. import java.util.Set;
  6. /**
  7.  * @author 言曌
  8.  * @date 2017/12/11 下午7:46
  9.  */
  10. @Entity
  11. @Table(name = "article")
  12. public class Article implements Serializable {
  13.     private static final long serialVersionUID = 7419229779731522702L;
  14.     @Id
  15.     @GeneratedValue(strategy = GenerationType.IDENTITY)
  16.     private Integer id;
  17.     @Lob//text
  18.     @Column(columnDefinition="text")
  19.     private String title;
  20.     @Lob //longtext
  21.     @Column(columnDefinition="longtext")
  22.     private String content;
  23.     private Integer userId;
  24.     private Integer likeCount;
  25.     private Date createTime;
  26.     private Date updateTime;
  27.     private Integer status;
  28.     @OneToMany(mappedBy = "article",cascade = CascadeType.ALL, orphanRemoval = true)
  29.     private Set<ArticleCategory> articleCategoryList;
  30.     public Integer getId() {
  31.         return id;
  32.     }
  33.     public void setId(Integer id) {
  34.         this.id = id;
  35.     }
  36.     public String getTitle() {
  37.         return title;
  38.     }
  39.     public void setTitle(String title) {
  40.         this.title = title;
  41.     }
  42.     public String getContent() {
  43.         return content;
  44.     }
  45.     public void setContent(String content) {
  46.         this.content = content;
  47.     }
  48.     public Integer getUserId() {
  49.         return userId;
  50.     }
  51.     public void setUserId(Integer userId) {
  52.         this.userId = userId;
  53.     }
  54.     public Integer getLikeCount() {
  55.         return likeCount;
  56.     }
  57.     public void setLikeCount(Integer likeCount) {
  58.         this.likeCount = likeCount;
  59.     }
  60.     public Date getCreateTime() {
  61.         return createTime;
  62.     }
  63.     public void setCreateTime(Date createTime) {
  64.         this.createTime = createTime;
  65.     }
  66.     public Date getUpdateTime() {
  67.         return updateTime;
  68.     }
  69.     public void setUpdateTime(Date updateTime) {
  70.         this.updateTime = updateTime;
  71.     }
  72.     public Integer getStatus() {
  73.         return status;
  74.     }
  75.     public void setStatus(Integer status) {
  76.         this.status = status;
  77.     }
  78.     public static long getSerialVersionUID() {
  79.         return serialVersionUID;
  80.     }
  81.     public Set<ArticleCategory> getArticleCategoryList() {
  82.         return articleCategoryList;
  83.     }
  84.     public void setArticleCategoryList(Set<ArticleCategory> articleCategoryList) {
  85.         this.articleCategoryList = articleCategoryList;
  86.     }
  87. }

注意 43-44 行

 

2、實體類 Category.java

  1. package com.liuyanzhao.blog.entity;
  2. import javax.persistence.*;
  3. import java.io.Serializable;
  4. import java.util.Set;
  5. /**
  6.  * @author 言曌
  7.  * @date 2017/12/11 下午8:16
  8.  */
  9. @Entity
  10. @Table(name = "category")
  11. public class Category implements Serializable {
  12.     private static final long serialVersionUID = 7419229779731522702L;
  13.     @Id
  14.     @GeneratedValue(strategy = GenerationType.IDENTITY)
  15.     private Integer id;
  16.     private String name;
  17.     private String key;
  18.     private Integer status;
  19.     @OneToMany(mappedBy = "category")
  20.     private Set<ArticleCategory> articleCategoryList;
  21.     public Integer getId() {
  22.         return id;
  23.     }
  24.     public void setId(Integer id) {
  25.         this.id = id;
  26.     }
  27.     public String getName() {
  28.         return name;
  29.     }
  30.     public void setName(String name) {
  31.         this.name = name;
  32.     }
  33.     public Integer getStatus() {
  34.         return status;
  35.     }
  36.     public void setStatus(Integer status) {
  37.         this.status = status;
  38.     }
  39.     public String getKey() {
  40.         return key;
  41.     }
  42.     public void setKey(String key) {
  43.         this.key = key;
  44.     }
  45.     public static long getSerialVersionUID() {
  46.         return serialVersionUID;
  47.     }
  48.     public Set<ArticleCategory> getArticleCategoryList() {
  49.         return articleCategoryList;
  50.     }
  51.     public void setArticleCategoryList(Set<ArticleCategory> articleCategoryList) {
  52.         this.articleCategoryList = articleCategoryList;
  53.     }
  54. }

注意 28-29 行

 

 

3、實體類 ArticleCategory.java

  1. package com.liuyanzhao.blog.entity;
  2. import javax.persistence.*;
  3. import java.io.Serializable;
  4. /**
  5.  * @author 言曌
  6.  * @date 2017/12/12 下午4:08
  7.  */
  8. @Entity
  9. @Table(name = "article_category")
  10. public class ArticleCategory implements Serializable {
  11.     private static final long serialVersionUID = 7419229779731522702L;
  12.     @Id
  13.     @ManyToOne
  14.     @JoinColumn(name = "article_id")
  15.     private Article article;
  16.     @Id
  17.     @ManyToOne
  18.     @JoinColumn(name = "category_id")
  19.     private Category category;
  20.     public static long getSerialVersionUID() {
  21.         return serialVersionUID;
  22.     }
  23.     public Article getArticle() {
  24.         return article;
  25.     }
  26.     public void setArticle(Article article) {
  27.         this.article = article;
  28.     }
  29.     public Category getCategory() {
  30.         return category;
  31.     }
  32.     public void setCategory(Category category) {
  33.         this.category = category;
  34.     }
  35. }

注意 17-25 行

 

Dao 層

1、ArticleDao.java

  1. package com.liuyanzhao.blog.dao;
  2. import com.liuyanzhao.blog.entity.Article;
  3. import com.liuyanzhao.blog.vo.ArticleVO;
  4. import org.springframework.data.domain.Page;
  5. import org.springframework.data.domain.Pageable;
  6. import org.springframework.data.jpa.repository.JpaRepository;
  7. /**
  8.  * @author 言曌
  9.  * @date 2017/11/28 下午3:31
  10.  */
  11. public interface ArticleDao extends JpaRepository<Article, Integer> {
  12.     //獲取文章列表,按status和id降序
  13.     Page<ArticleVO> findAllByOrderByStatusDescIdDesc(Pageable pageable);
  14. }

 

2、CategoryDao.java

  1. package com.liuyanzhao.blog.dao;
  2. import com.liuyanzhao.blog.entity.Category;
  3. import org.springframework.data.jpa.repository.JpaRepository;
  4. /**
  5.  * @author 言曌
  6.  * @date 2017/12/12 上午11:16
  7.  */
  8. public interface CategoryDao  extends JpaRepository<Category, Integer> {
  9. }

 

Service 層

1、ArticleService.java

  1. package com.liuyanzhao.blog.service;
  2. import com.liuyanzhao.blog.vo.ArticleVO;
  3. import org.springframework.data.domain.Page;
  4. import org.springframework.data.domain.Pageable;
  5. /**
  6.  * @author 言曌
  7.  * @date 2017/12/9 下午4:10
  8.  */
  9. public interface ArticleService {
  10.     //獲得文章列表
  11.     Page<ArticleVO> findAll(Pageable pageable);
  12. }

 

2、ArticleServiceImpl.java

  1. package com.liuyanzhao.blog.service.Impl;
  2. import com.liuyanzhao.blog.dao.ArticleDao;
  3. import com.liuyanzhao.blog.service.ArticleService;
  4. import com.liuyanzhao.blog.vo.ArticleVO;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.data.domain.Page;
  7. import org.springframework.data.domain.Pageable;
  8. import org.springframework.stereotype.Service;
  9. import javax.transaction.Transactional;
  10. /**
  11.  * @author 言曌
  12.  * @date 2017/12/9 下午4:10
  13.  */
  14. @Service("articleService")
  15. @Transactional
  16. public class ArticleServiceImpl implements ArticleService {
  17.     @Autowired
  18.     private ArticleDao articleDao;
  19.     @Override
  20.     public Page<ArticleVO> findAll(Pageable pageable) {
  21.         Page<ArticleVO> articleVOPage = articleDao.findAllByOrderByStatusDescIdDesc(pageable);
  22.         return articleVOPage;
  23.     }
  24. }

 

 

Controller 層

ArticleController.java

  1. package com.liuyanzhao.blog.controller;
  2. import com.liuyanzhao.blog.service.ArticleService;
  3. import com.liuyanzhao.blog.vo.ArticleVO;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.data.domain.Page;
  6. import org.springframework.data.domain.PageRequest;
  7. import org.springframework.stereotype.Controller;
  8. import org.springframework.web.bind.annotation.*;
  9. import org.springframework.web.servlet.ModelAndView;
  10. /**
  11.  * @author 言曌
  12.  * @date 2017/11/28 下午3:33
  13.  */
  14. @Controller
  15. public class ArticleController {
  16.     @Autowired
  17.     private ArticleService articleService;
  18.     @RequestMapping(value = "/admin/article")
  19.     public ModelAndView listUser(@RequestParam(value = "page",defaultValue = "1") Integer page,
  20.                                  @RequestParam(value = "size",defaultValue = "10") Integer size) {
  21.         ModelAndView modelAndView = new ModelAndView();
  22.         PageRequest request = new PageRequest(page-1,size);
  23.         Page<ArticleVO> articleVOPage = articleService.findAll(request);
  24.         modelAndView.addObject("articleVOPage",articleVOPage);
  25.         modelAndView.setViewName("/admin/article/list");
  26.         return modelAndView;
  27.     }
  28. }

 

檢視層

檢視層主要看錶格的列印吧,分頁部分和其他內容就不貼出來了

  1. <table class="table table-bordered">
  2.           <tr>
  3.               <th><input type="checkbox" id="allSelect" onclick="DoCheck()"></th>
  4.               <th>ID</th>
  5.               <th>作者</th>
  6.               <th>標題</th>
  7.               <th>分類</th>
  8.               <th>更新時間</th>
  9.               <th>操作</th>
  10.           </tr>
  11.           <c:forEach var="article" items="${articleVOPage.content}">
  12.               <tr>
  13.                   <td><input type="checkbox" name="ids" value="${article.id}"></td>
  14.                   <td>${article.id}</td>
  15.                   <td>${article.userId}</td>
  16.                   <td><a href="">${article.title}</a></td>
  17.                   <td>
  18.                       <c:forEach var="c" items="${article.articleCategoryList}">
  19.                           <a href="">${c.category.name}</a> &nbsp;
  20.                       </c:forEach>
  21.                   </td>
  22.                   <td>${article.updateTime}</td>
  23.                   <td>
  24.                       <a href="${pageContext.request.contextPath}/admin/user/profile/${article.id}">
  25.                           <button type="button" class="btn btn-success btn-xs">檢視</button>
  26.                       </a>
  27.                       <button type="button" class="btn btn-danger btn-xs"
  28.                               onclick="deleteUser(${article.id})">刪除
  29.                       </button>
  30.                       <a href="${pageContext.request.contextPath}/admin/user/edit/${article.id}">
  31.                           <button type="button" class="btn btn-primary btn-xs">編輯</button>
  32.                       </a>
  33.                   </td>
  34.               </tr>
  35.           </c:forEach>
  36.       </table>

 

最終效果圖就是上面的

Spring Data JPA 實現多表關聯查詢

 

 

本文地址:https://liuyanzhao.com/6978.html

相關文章