Spring Data JPA 实现多表关联查询

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

先用两个好东西可以用来转换Do,To,Vo等对象互转

UserActionForm uForm = (UserActionForm) form;  
// 构造一个User对象  
User user = new User();  
// 逐一赋值  
user.setUsername(uForm.getUsername);  
user.setPassword(uForm.getPassword);  
user.setAge(uForm.getAge);  

#转换后删除多余参数
BeanUtils.copyProperties("要转换的类", "转换后的类");  
#转换后不删除多余参数
PropertyUtils.copyProperties("要转换的类", "转换后的类");

需求描述

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

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


image.png

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

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

如图像这样

代码实现

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

实体类

package com.liuyanzhao.blog.entity;
import javax.persistence.*;
import java.io.Serializable;
import java.util.Date;
import java.util.Set;
/**
 * @author 言曌
 * @date 2017/12/11 下午7:46
 */
@Entity
@Table(name = "article")
public class Article implements Serializable {
    private static final long serialVersionUID = 7419229779731522702L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    @Lob//text
    @Column(columnDefinition="text")
    private String title;
    @Lob //longtext
    @Column(columnDefinition="longtext")
    private String content;
    private Integer userId;
    private Integer likeCount;
    private Date createTime;
    private Date updateTime;
    private Integer status;
    @OneToMany(mappedBy = "article",cascade = CascadeType.ALL, orphanRemoval = true)
    private Set<ArticleCategory> articleCategoryList;
    public Integer getId() {
        return id;
    }
    public void setId(Integer 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 Integer getUserId() {
        return userId;
    }
    public void setUserId(Integer userId) {
        this.userId = userId;
    }
    public Integer getLikeCount() {
        return likeCount;
    }
    public void setLikeCount(Integer likeCount) {
        this.likeCount = likeCount;
    }
    public Date getCreateTime() {
        return createTime;
    }
    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }
    public Date getUpdateTime() {
        return updateTime;
    }
    public void setUpdateTime(Date updateTime) {
        this.updateTime = updateTime;
    }
    public Integer getStatus() {
        return status;
    }
    public void setStatus(Integer status) {
        this.status = status;
    }
    public static long getSerialVersionUID() {
        return serialVersionUID;
    }
    public Set<ArticleCategory> getArticleCategoryList() {
        return articleCategoryList;
    }
    public void setArticleCategoryList(Set<ArticleCategory> articleCategoryList) {
        this.articleCategoryList = articleCategoryList;
    }
}

注意 43-44 行@OneToMany(mappedBy = "article",cascade = CascadeType.ALL, orphanRemoval = true)

2、实体类 Category.java

package com.liuyanzhao.blog.entity;
import javax.persistence.*;
import java.io.Serializable;
import java.util.Set;
/**
 * @author 言曌
 * @date 2017/12/11 下午8:16
 */
@Entity
@Table(name = "category")
public class Category implements Serializable {
    private static final long serialVersionUID = 7419229779731522702L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String name;
    private String key;
    private Integer status;
    @OneToMany(mappedBy = "category")
    private Set<ArticleCategory> articleCategoryList;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getStatus() {
        return status;
    }
    public void setStatus(Integer status) {
        this.status = status;
    }
    public String getKey() {
        return key;
    }
    public void setKey(String key) {
        this.key = key;
    }
    public static long getSerialVersionUID() {
        return serialVersionUID;
    }
    public Set<ArticleCategory> getArticleCategoryList() {
        return articleCategoryList;
    }
    public void setArticleCategoryList(Set<ArticleCategory> articleCategoryList) {
        this.articleCategoryList = articleCategoryList;
    }
}

注意 28-29 行 @OneToMany(mappedBy = "category")
3、实体类 ArticleCategory.java

package com.liuyanzhao.blog.entity;
import javax.persistence.*;
import java.io.Serializable;
/**
 * @author 言曌
 * @date 2017/12/12 下午4:08
 */
@Entity
@Table(name = "article_category")
public class ArticleCategory implements Serializable {
    private static final long serialVersionUID = 7419229779731522702L;
    @Id
    @ManyToOne
    @JoinColumn(name = "article_id")
    private Article article;
    @Id
    @ManyToOne
    @JoinColumn(name = "category_id")
    private Category category;
    public static long getSerialVersionUID() {
        return serialVersionUID;
    }
    public Article getArticle() {
        return article;
    }
    public void setArticle(Article article) {
        this.article = article;
    }
    public Category getCategory() {
        return category;
    }
    public void setCategory(Category category) {
        this.category = category;
    }
}

注意 17-25 行
@Id
@ManyToOne
@JoinColumn(name = "article_id")
private Article article;
@Id
@ManyToOne
@JoinColumn(name = "category_id")
private Category category;

Dao 层

1、ArticleDao.java

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

2、CategoryDao.java

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

Service 层
1、ArticleService.java

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

2、ArticleServiceImpl.java

package com.liuyanzhao.blog.service.Impl;
import com.liuyanzhao.blog.dao.ArticleDao;
import com.liuyanzhao.blog.service.ArticleService;
import com.liuyanzhao.blog.vo.ArticleVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import javax.transaction.Transactional;
/**
 * @author 言曌
 * @date 2017/12/9 下午4:10
 */
@Service("articleService")
@Transactional
public class ArticleServiceImpl implements ArticleService {
    @Autowired
    private ArticleDao articleDao;
    @Override
    public Page<ArticleVO> findAll(Pageable pageable) {
        Page<ArticleVO> articleVOPage = articleDao.findAllByOrderByStatusDescIdDesc(pageable);
        return articleVOPage;
    }
}

Controller 层
ArticleController.java

package com.liuyanzhao.blog.controller;
import com.liuyanzhao.blog.service.ArticleService;
import com.liuyanzhao.blog.vo.ArticleVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
/**
 * @author 言曌
 * @date 2017/11/28 下午3:33
 */
@Controller
public class ArticleController {
    @Autowired
    private ArticleService articleService;
    @RequestMapping(value = "/admin/article")
    public ModelAndView listUser(@RequestParam(value = "page",defaultValue = "1") Integer page,
                                 @RequestParam(value = "size",defaultValue = "10") Integer size) {
        ModelAndView modelAndView = new ModelAndView();
        PageRequest request = new PageRequest(page-1,size);
        Page<ArticleVO> articleVOPage = articleService.findAll(request);
        modelAndView.addObject("articleVOPage",articleVOPage);
        modelAndView.setViewName("/admin/article/list");
        return modelAndView;
    }
}

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

<table class="table table-bordered">
          <tr>
              <th><input type="checkbox" id="allSelect" onclick="DoCheck()"></th>
              <th>ID</th>
              <th>作者</th>
              <th>标题</th>
              <th>分类</th>
              <th>更新时间</th>
              <th>操作</th>
          </tr>
          <c:forEach var="article" items="${articleVOPage.content}">
              <tr>
                  <td><input type="checkbox" name="ids" value="${article.id}"></td>
                  <td>${article.id}</td>
                  <td>${article.userId}</td>
                  <td><a href="">${article.title}</a></td>
                  <td>
                      <c:forEach var="c" items="${article.articleCategoryList}">
                          <a href="">${c.category.name}</a> &nbsp;
                      </c:forEach>
                  </td>
                  <td>${article.updateTime}</td>
                  <td>
                      <a href="${pageContext.request.contextPath}/admin/user/profile/${article.id}">
                          <button type="button" class="btn btn-success btn-xs">查看</button>
                      </a>
                      <button type="button" class="btn btn-danger btn-xs"
                              onclick="deleteUser(${article.id})">删除
                      </button>
                      <a href="${pageContext.request.contextPath}/admin/user/edit/${article.id}">
                          <button type="button" class="btn btn-primary btn-xs">编辑</button>
                      </a>
                  </td>
              </tr>
          </c:forEach>
      </table>

最终效果图就是上面的
image

本文转载来源地址:https://liuyanzhao.com/6978.html

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,546评论 6 507
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,224评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,911评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,737评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,753评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,598评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,338评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,249评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,696评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,888评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,013评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,731评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,348评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,929评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,048评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,203评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,960评论 2 355

推荐阅读更多精彩内容