解析JPA的視圖查訊問題。本站提示廣大學習愛好者:(解析JPA的視圖查訊問題)文章只能為提供參考,不一定能成為您想要的結果。以下是解析JPA的視圖查訊問題正文
昨天早晨碰到一個需求,天天早上要生成一份申報給各個部分的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 > </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的相干技巧,異常適用。