昨天晚上遇到一個需求,每天早上要生成一份報告給各個部門的Leader。實現方式基本上確定為HTML格式的電子郵件。但是數據方面犯了難。原因在于數據庫中存儲的數據是跨表的,而且還要做count統計,這樣得到的結果就不是原生的MySQL表,我用的又是JPA技術。我們知道,使用JPA第一步就是映射實體,每一張表就至少對應一個實體(力求嚴謹,因為聯合主鍵時一張表會對應兩個對象)。可是對于靈活的查詢尤其是連接查詢,并不存在一個真正的表與其對應,怎么樣才能解決呢?來,我們來舉個“栗子”
假設我們有兩張表,一張學院表,一張學生表。學院表里存著學院ID和學院名稱,學生表里存著學生的基本信息,包括學號、學院ID和學生姓名(其它較復雜的屬性我們不看了),正如下面的建表語句所示:
-- ----------------------------
-- 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', '藝術學院');
-- ----------------------------
-- 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', '讓雷諾');
使用Group By和不使用Group By:
我們按照往常編碼那樣,從一個主要的實體操作服務中暴露出EntityManager來:
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;
}
}
然后我們還需要和以前一樣構造兩個表的實體類:
學院表的實體類:
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...
}
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...
}
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...
}
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;
}
}
另外,向大家推薦一本書――Apress出版社出版的《Pro JPA 2 Mastering the Java trade Persistence API》,這本書詳細介紹了JPA的相關技術,非常實用。
新聞熱點
疑難解答