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