亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > Java > 正文

解析JPA的視圖查詢問題

2019-11-26 15:51:57
字體:
來源:轉載
供稿:網友

昨天晚上遇到一個需求,每天早上要生成一份報告給各個部門的Leader。實現方式基本上確定為HTML格式的電子郵件。但是數據方面犯了難。原因在于數據庫中存儲的數據是跨表的,而且還要做count統計,這樣得到的結果就不是原生的MySQL表,我用的又是JPA技術。我們知道,使用JPA第一步就是映射實體,每一張表就至少對應一個實體(力求嚴謹,因為聯合主鍵時一張表會對應兩個對象)??墒菍τ陟`活的查詢尤其是連接查詢,并不存在一個真正的表與其對應,怎么樣才能解決呢?來,我們來舉個“栗子”

假設我們有兩張表,一張學院表,一張學生表。學院表里存著學院ID和學院名稱,學生表里存著學生的基本信息,包括學號、學院ID和學生姓名(其它較復雜的屬性我們不看了),正如下面的建表語句所示:

復制代碼 代碼如下:

-- ----------------------------
-- Table structure for `depts`
-- ----------------------------
DROP TABLE IF EXISTS `depts`;
CREATE TABLE `depts` (
  `deptId` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '學院ID',
  `deptName` varchar(50) NOT NULL COMMENT '學院名稱',
  PRIMARY KEY (`deptId`)
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of depts
-- ----------------------------
INSERT INTO `depts` VALUES ('1', '哲學院');
INSERT INTO `depts` VALUES ('2', '經濟學院');
INSERT INTO `depts` VALUES ('3', '法學院');
INSERT INTO `depts` VALUES ('4', '教育學院');
INSERT INTO `depts` VALUES ('5', '文學院');
INSERT INTO `depts` VALUES ('6', '歷史學院');
INSERT INTO `depts` VALUES ('7', '理學院');
INSERT INTO `depts` VALUES ('8', '工學院');
INSERT INTO `depts` VALUES ('9', '農學院');
INSERT INTO `depts` VALUES ('10', '醫學院');
INSERT INTO `depts` VALUES ('11', '軍事學院');
INSERT INTO `depts` VALUES ('12', '管理學院');
INSERT INTO `depts` VALUES ('13', '藝術學院');


再建立一個學生表,再隨便往里面插入點數據:
復制代碼 代碼如下:

-- ----------------------------
-- Table structure for `students`
-- ----------------------------
DROP TABLE IF EXISTS `students`;
CREATE TABLE `students` (
  `stuNo` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '學號 從1000開始',
  `deptId` int(10) unsigned NOT NULL COMMENT '學院ID',
  `stuName` varchar(50) NOT NULL COMMENT '學生姓名',
  PRIMARY KEY (`stuNo`),
  KEY `FK_DEPTID` (`deptId`),
  CONSTRAINT `FK_DEPTID` FOREIGN KEY (`deptId`) REFERENCES `depts` (`deptId`) ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=1006 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of students
-- ----------------------------
INSERT INTO `students` VALUES ('1000', '13', '鳥叔');
INSERT INTO `students` VALUES ('1001', '7', '喬布斯');
INSERT INTO `students` VALUES ('1002', '3', '阿湯哥');
INSERT INTO `students` VALUES ('1003', '3', '施瓦辛格');
INSERT INTO `students` VALUES ('1004', '2', '貝克漢姆');
INSERT INTO `students` VALUES ('1005', '3', '讓雷諾');


現在我們想統計一下各個學院都有多少學生。這個題目在我們學習SQL的時候再簡單不過了。兩種實現方法:

使用Group By和不使用Group By:

復制代碼 代碼如下:

SELECT b.deptId, b.deptName, count(*) as 'totalCount' FROM students a LEFT JOIN depts b ON a.deptId=b.deptId GROUP BY b.deptId ORDER BY b.deptId;

使用Group By之后,凡是沒有對應學生記錄的學院都沒有顯示出來(我不明白為什么。。。如果有人知道的話麻煩告訴我好嗎?)
復制代碼 代碼如下:

+--------+--------------+------------+
| deptId | deptName     | totalCount |
+--------+--------------+------------+
|      2 | 經濟學院     |          1 |
|      3 | 法學院       |          3 |
|      7 | 理學院       |          1 |
|     13 | 藝術學院     |          1 |
+--------+--------------+------------+

再來一個不使用Group By的查詢:
復制代碼 代碼如下:

SELECT a.deptId, a.deptName, (SELECT count(*) FROM students b where b.deptId=a.deptId) as 'totalCount' FROM depts a;

這次就完全顯示出來了:
復制代碼 代碼如下:

+--------+--------------+------------+
| deptId | deptName     | totalCount |
+--------+--------------+------------+
|      1 | 哲學院       |          0 |
|      2 | 經濟學院     |          1 |
|      3 | 法學院       |          3 |
|      4 | 教育學院     |          0 |
|      5 | 文學院       |          0 |
|      6 | 歷史學院     |          0 |
|      7 | 理學院       |          1 |
|      8 | 工學院       |          0 |
|      9 | 農學院       |          0 |
|     10 | 醫學院       |          0 |
|     11 | 軍事學院     |          0 |
|     12 | 管理學院     |          0 |
|     13 | 藝術學院     |          1 |
+--------+--------------+------------+

至此,我們的SQL寫通了。但是怎么才能使用JPA來查詢出一樣的視圖呢?

我們按照往常編碼那樣,從一個主要的實體操作服務中暴露出EntityManager來:

復制代碼 代碼如下:

package net.csdn.blog.chaijunkun.dao;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.springframework.stereotype.Service;

@Service
public class ObjectDaoServiceImpl implements ObjectDaoService {

 @PersistenceContext
 private EntityManager entityManager;

 @Override
 public EntityManager getEntityManager(){
  return this.entityManager;
 }

}


這樣做的好處就是所有的數據操作都來源于同一個實體管理器。將來若部署發生變化,只改這一處注入就可以了。

然后我們還需要和以前一樣構造兩個表的實體類:

學院表的實體類:

復制代碼 代碼如下:

package net.csdn.blog.chaijunkun.pojo;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name="depts")
public class Depts implements Serializable {

 /**
  *
  */
 private static final long serialVersionUID = 3602227759878736655L;

 @Id
 @GeneratedValue(strategy= GenerationType.AUTO)
 @Column(name= "deptId")
 private Integer deptId;

 @Column(name= "deptName", length= 50, nullable= false)
 private String deptName;

 //getters and setters...
}


學生表的實體類:
復制代碼 代碼如下:

package net.csdn.blog.chaijunkun.pojo;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Entity
@Table(name= "students")
public class Students implements Serializable {

 /**
  *
  */
 private static final long serialVersionUID = -5942212163629824609L;

 @Id
 @GeneratedValue(strategy= GenerationType.AUTO)
 @Column(name= "stuNo")
 private Long stuNo;

 @ManyToOne
 @JoinColumn(name= "deptId", nullable= false)<SPAN style="WHITE-SPACE: pre"> </SPAN>
 private Depts depts;

 @Column(name= "stuName", length= 50, nullable= false)
 private String stuName;

 //getters and setters...

}


兩個實體類都構造好了,我們接下來還要弄一個視圖類,屬性的類型完全由你想要的結構來構造。例如這個例子中我們要學院編號,學院名稱和總人數。那么我們就這么定義:
復制代碼 代碼如下:

package net.csdn.blog.chaijunkun.pojo;

import java.io.Serializable;

public class Report implements Serializable {

 /**
  *
  */
 private static final long serialVersionUID = 4497500574990765498L;

 private Integer deptId;

 private String deptName;

 private Integer totalCount;

 public Report(){};

 public Report(Integer deptId, String deptName, Integer totalCount) {
  this.deptId = deptId;
  this.deptName = deptName;
  this.totalCount = totalCount;
 }

 //getters and setters...

}


可以說,視圖對象的定義比實體定義還要簡單,不需要注解,不需要映射(以上代碼為了減少代碼量均省去了各屬性的get和set方法,請自行添加)。但是唯一不同的是我們需要額外構造一個帶有字段初始化的構造函數。并且還不能覆蓋默認的無參構造函數。然后我們就開始進入真正的查詢了(作為視圖來講,SQL規范中是不允許修改數據的。因此,視圖僅有SELECT特性。這也是為什么很多人使用JPA想通過實體映射數據庫內建視圖的方式進行查詢,卻始終映射不成功的癥結所在。
復制代碼 代碼如下:

package net.csdn.blog.chaijunkun.dao;

import java.util.List;

import javax.annotation.Resource;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;

import org.springframework.stereotype.Service;

import net.csdn.blog.chaijunkun.pojo.Depts;
import net.csdn.blog.chaijunkun.pojo.Report;
import net.csdn.blog.chaijunkun.pojo.Students;

@Service
public class ReportServiceImpl implements ReportService {

 @Resource
 private ObjectDaoService objectDaoService;

 @Override
 public List<Report> getReport() {
  String jpql= String.format("select new %3$s(a.deptId, a.deptName, (select count(*) from %2$s b where b.deptId= a.deptId) as totalCount) from %1$s a",
    Depts.class.getName(),
    Students.class.getName(),
    Report.class.getName());

  EntityManager entityManager= objectDaoService.getEntityManager();
  //建立有類型的查詢
  TypedQuery<Report> reportTypedQuery= entityManager.createQuery(jpql, Report.class);
  //另外有詳細查詢條件的在jpql中留出參數位置來(?1 ?2 ?3....),然后在這設置
  //reportTypedQuery.setParameter(1, params);
  List<Report> reports= reportTypedQuery.getResultList();
  return reports;
 }

}


在上面的代碼中我們構造了JPQL中的視圖查詢語句。最重要的就是要在最初的select后面new出新的對象。然后把我們查詢到的結果通過視圖對象的構造函數灌入各個屬性。由統計生成的字段最好用as重命名結果以保持和視圖對象屬性名稱相同。這樣,我們就得到了視圖數據。接下來就去嘗試遍歷這個List吧,操作非常方便。

另外,向大家推薦一本書――Apress出版社出版的《Pro JPA 2 Mastering the Java trade Persistence API》,這本書詳細介紹了JPA的相關技術,非常實用。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久久久国产精品免费| 久久精品国产免费观看| 亚洲成人中文字幕| 欧美国产亚洲视频| 91网站在线看| 国产精品99久久久久久白浆小说| 中文字幕日韩综合av| 色999日韩欧美国产| 在线播放日韩精品| 成人有码在线视频| 日韩成人中文字幕在线观看| 一区二区三区天堂av| 欧美有码在线观看| 亚洲爱爱爱爱爱| 亚洲视频网站在线观看| 亚洲电影免费观看高清| 亚洲免费电影在线观看| 精品久久久一区二区| 亚洲成人av中文字幕| 2018中文字幕一区二区三区| 91亚洲精品一区| 91社影院在线观看| 欧美另类在线观看| 一区二区福利视频| 日韩久久午夜影院| 亚洲男人天堂网| 欧美在线一区二区三区四| 久久久久久香蕉网| 久久久免费观看| 丝袜一区二区三区| 亚洲成年人在线播放| 亚洲a在线播放| 一区二区亚洲精品国产| 欧美亚洲一区在线| 日韩在线观看网址| 日韩精品极品视频免费观看| 91久久精品国产91久久性色| 久久久久久久久爱| 欧美国产在线视频| 久久综合88中文色鬼| 欧美大片免费观看| 亚洲自拍偷拍在线| 色偷偷偷亚洲综合网另类| 国产高清视频一区三区| 国产91精品高潮白浆喷水| 久久成人18免费网站| 日韩美女免费观看| 欧美国产亚洲视频| 久久久伊人欧美| 国产精品久久久久福利| 欧美刺激性大交免费视频| 精品色蜜蜜精品视频在线观看| 国产成人精品免高潮在线观看| 日韩久久午夜影院| 欧美疯狂做受xxxx高潮| 久久91精品国产91久久久| 激情成人中文字幕| 97视频在线免费观看| 欧美福利视频网站| xxx成人少妇69| 欧美一级大片在线观看| 欧美国产日韩视频| 亚洲女人被黑人巨大进入al| 中文字幕一区日韩电影| 国产欧洲精品视频| 疯狂欧美牲乱大交777| 久久免费视频在线| 国产精品久久婷婷六月丁香| 国产精品色悠悠| 2018中文字幕一区二区三区| 欧美精品一区在线播放| 国产精品久久久久久久久免费| 国产一区二区三区在线免费观看| 日韩av一区二区在线观看| 国产成人精品在线视频| 国产又爽又黄的激情精品视频| 欧美亚洲国产成人精品| 91久久久国产精品| 久久国产视频网站| 亚洲精品网站在线播放gif| 亚洲成人激情视频| 97在线日本国产| 国产亚洲欧美一区| 国产丝袜一区二区三区| 欧美成人精品不卡视频在线观看| 欧美精品性视频| 色偷偷91综合久久噜噜| 日韩高清中文字幕| 国产精品网站入口| 日本精品一区二区三区在线播放视频| 91色p视频在线| 久久视频在线播放| 欧美福利视频在线观看| 欧美又大粗又爽又黄大片视频| 欧美日韩成人精品| 国产欧美精品在线| 国产精品久久久久久亚洲调教| 亚洲免费一级电影| 精品福利樱桃av导航| 国产欧美精品xxxx另类| 欧美电影院免费观看| 国产日韩欧美夫妻视频在线观看| 亚洲国产高潮在线观看| 成人夜晚看av| 中日韩美女免费视频网站在线观看| 亚洲色图国产精品| 亚洲高清一区二| 日本高清不卡在线| 91精品国产高清久久久久久91| 国产精品爽黄69天堂a| 欧美综合激情网| 亚洲精品国产综合区久久久久久久| 久久精品视频在线| 日韩一区二区三区xxxx| 日韩国产高清污视频在线观看| 亚洲xxxxx电影| 国产精品美女免费视频| 亚洲精品自在久久| 久久精视频免费在线久久完整在线看| 日韩美女视频免费看| 国产精品看片资源| 久久久久久久激情视频| 久久久久成人网| 欧美激情久久久久久| 亚洲一级黄色片| 菠萝蜜影院一区二区免费| 亚洲电影中文字幕| 久久精品亚洲国产| 欧美一级在线亚洲天堂| 国产午夜精品一区二区三区| 欧美精品videosex极品1| 精品国产31久久久久久| 国产精品久久久久久久一区探花| 欧美精品精品精品精品免费| 国产精品伦子伦免费视频| 亚洲国产精品成人精品| 日韩免费观看av| 欧美成人一区二区三区电影| 色与欲影视天天看综合网| 亚洲视屏在线播放| 国产精品视频色| 欧美国产在线电影| 777国产偷窥盗摄精品视频| 亚洲春色另类小说| 久久久久久69| 91丨九色丨国产在线| 国产日韩中文字幕| 成人性生交大片免费看视频直播| 国内精品久久久久影院 日本资源| 中文字幕欧美日韩精品| 最近2019中文字幕一页二页| 日韩av电影手机在线观看| 96pao国产成视频永久免费| 日韩av电影手机在线| 91国内揄拍国内精品对白| 亚洲国产中文字幕在线观看| 国产午夜精品理论片a级探花| 成人在线免费观看视视频| 中文字幕亚洲欧美日韩在线不卡| 538国产精品一区二区免费视频| 精品欧美一区二区三区| 久久精品亚洲94久久精品| 国产精品视频精品| 亚洲va久久久噜噜噜久久天堂|