Spring Data JPA 实现多表关联查询

最近抽出时间来做博客,数据库操作使用的是 JPA,相对比 Mybatis 而言,JPA 单表操作非常方便,增删改查都已经写好了。但是多表操作就不如 Mybatis 那种直接写 sql 语句来得方便,JPA 的多表操作比较麻烦。

 

需求描述

获得文章列表,文章列表里需要显示每篇文章的分类目录列表,因为一个文章可能有多个分类,一个分类当然也可以对应多篇文章的。

 

下面是我用截图软件画的一个图,描述的是三张表和其主要字段。

 

文章表 article 和分类表 category 通过 中间表 article_category 关联

 

我们的需求也很简单,从数据库里查询所有文章,并给每篇文章加一个分类列表的属性。

如图像这样

 

代码实现

Spring Data JPA 需要的依赖和配置文件这里就不给出了,因为不是本文的重点。

 

实体类

1、实体类 Article.java

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

注意 43-44 行

 

2、实体类 Category.java

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

注意 28-29 行

 

 

3、实体类 ArticleCategory.java

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

注意 17-25 行

 

Dao 层

1、ArticleDao.java

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

 

2、CategoryDao.java

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

 

Service 层

1、ArticleService.java

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

 

2、ArticleServiceImpl.java

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

 

 

Controller 层

ArticleController.java

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

 

视图层

视图层主要看表格的打印吧,分页部分和其他内容就不贴出来了

  1. <table class="table table-bordered">
  2.           <tr>
  3.               <th><input type="checkbox" id="allSelect" οnclick="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.                               οnclick="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>

 

最终效果图就是上面的

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值