您现在的位置: 万盛学电脑网 >> 程序编程 >> 脚本专题 >> javascript >> 正文

解析JPA的视图查询问题

作者:佚名    责任编辑:admin    更新时间:2022-06-22

        这篇文章主要是对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