一、SQL查詢簡介
使用SQL查詢可以利用某些數據庫的特性,或者將原有的JDBC應用遷移到hibernate應用上,也可能需要使用原生的SQL查詢。查詢步驟如下:
1、獲取hibernate session對象
2、編寫SQL語句
3、以SQL語句作為參數,調用Session的createSQLQuery()方法創建查詢對象
4、調用SQLQuery對象的addScalar()huoaddEntity()方法將選出的結果與標量值或實體進行關聯,分別用於進行標量查詢或實體查詢
5、如果SQL語句有參數,則調用Query的setXxx()方法為參數賦值
6、調用Query的list()方法或uniqueResult()方法返回查詢的結果集
二、SQL查詢
1、標量查詢
標量查詢會獲得數據表列對應的Object數組組成的List,hibernate會默認通過ResultSetMetadata來判定所返回數據列的實際順序和類型,但這樣的默認處理會降低程序性能,因此在代碼書寫時建議明確返回值類型
String sql = "select * from sql_student"; SQLQuery q = session.createSQLQuery(sql) .addScalar("id", StandardBasicTypes.LONG)//明確返回值類型,屬性名稱必須和表中列名相同 .addScalar("sname", StandardBasicTypes.STRING) .addScalar("teacher_id", StandardBasicTypes.LONG); List list = q.list(); for(Object ob : list) { Object[] ob1 = (Object[]) ob; System.out.println(ob1[0] + " | " + ob1[1] + " | " + ob1[2]); }
多表查詢
String sql = "select t.tid, t.tname,s.sid,s.sname from sql_teacher t, sql_student s WHERE t.tid = s.teacher_id"; SQLQuery q = session.createSQLQuery(sql) .addScalar("t.tid", StandardBasicTypes.LONG)//明確返回值類型,屬性名稱必須和表中列名相同 .addScalar("t.tname", StandardBasicTypes.STRING) .addScalar("s.sid", StandardBasicTypes.LONG) .addScalar("s.sname", StandardBasicTypes.STRING); List list = q.list(); for(Object ob : list) { Object[] ob1 = (Object[]) ob; System.out.println(ob1[0] + " " + ob1[1] + " | " + ob1[2] + " " + ob1[3]); }
2、實體查詢
如果查詢返回了某個數據表的全部數據列,且該數據表有對應的持久化類映射,就可用實體查詢將查詢結果轉換成實體
String sql = "select * from sql_student"; SQLQuery q = session.createSQLQuery(sql) .addEntity(SQLStudent.class);//程序必須選出所有數據列才可被轉換成持久化實體 List<SQLStudent> list = q.list(); for(SQLStudent s : list) { System.out.println(s.getId() + " | " + s.getSname()+ " | " + s.getSqlTeacher().getName()); }
多表查詢(使用這種查詢,如果兩張表中有相同字段,則得到這兩字段值均為順序在前的字段的值,解決辦法是將表中名稱相同字段名稱做區別)
String sql = "SELECT s.*,t.* FROM sql_teacher t,sql_student s WHERE s.teacher_id = t.tid"; SQLQuery sqlQuery = session.createSQLQuery(sql) .addEntity("t", SQLTeacher.class) .addEntity("s", SQLStudent.class); List list = sqlQuery.list(); for (Object obj : list) { Object[] objects = (Object[]) obj; SQLTeacher sqlTeacher = (SQLTeacher) objects[0]; SQLStudent sqlStudent = (SQLStudent) objects[1]; System.out.println(sqlTeacher.getId() + " " + sqlTeacher.getTname() + " | " + sqlStudent.getId() + " " + sqlStudent.getSname()); }
3、關聯查詢
String sql = "SELECT t.*,s.* FROM sql_teacher t LEFT JOIN sql_student s ON t.tid = s.teacher_id"; SQLQuery sqlQuery = session.createSQLQuery(sql) .addEntity("t", SQLTeacher.class) .addEntity("s", SQLStudent.class); List list = sqlQuery.list(); for (Object obj : list) { Object[] objects = (Object[]) obj; SQLTeacher sqlTeacher = (SQLTeacher) objects[0]; SQLStudent sqlStudent = (SQLStudent) objects[1]; System.out.println(sqlTeacher.getId() + " " + sqlTeacher.getTname() + " | " + sqlStudent.getId() + " " + sqlStudent.getSname()); }
注意:兩個表中字段名稱不能重復,否則得到結果的相同名稱字段的值會出現混淆(只取順序排在前面的字段值)
測試實體類
@Entity @Table(name = "sql_teacher") public class SQLTeacher { @Id @GeneratedValue @Column(name = "tid") private Long id; @Column(name = "tname") private String tname; @OneToMany(targetEntity = SQLStudent.class, mappedBy = "sqlTeacher") private Set<SQLStudent> sqlStudents = new HashSet<SQLStudent>(); public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getTname() { return tname; } public void setTname(String tname) { this.tname = tname; } public Set<SQLStudent> getSqlStudents() { return sqlStudents; } public void setSqlStudents(Set<SQLStudent> sqlStudents) { this.sqlStudents = sqlStudents; } }
@Entity @Table(name = "sql_student") public class SQLStudent { @Id @GeneratedValue @Column(name = "sid") private Long id; @Column(name = "sname") private String sname; @ManyToOne(targetEntity = SQLTeacher.class) @JoinColumn(name = "teacher_id", referencedColumnName = "tid", nullable = false) private SQLTeacher sqlTeacher; //@Column(name = "teacher_id") //private Long teacherId; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getSname() { return sname; } public void setSname(String sname) { this.sname = sname; } public SQLTeacher getSqlTeacher() { return sqlTeacher; } public void setSqlTeacher(SQLTeacher sqlTeacher) { this.sqlTeacher = sqlTeacher; } /*public Long getTeacherId() { return teacherId; } public void setTeacherId(Long teacherId) { this.teacherId = teacherId; }*/ }
測試類
public class SQLController { public static void main(String[] args) { Configuration cf = new Configuration().configure(); SessionFactory sf = cf.buildSessionFactory(); Session session = sf.openSession(); Transaction ts = session.beginTransaction(); try { SQLTeacher t = new SQLTeacher(); t.setTname("teacher 3"); Serializable id = session.save(t); t = (SQLTeacher) session.get(SQLTeacher.class, id); SQLStudent s1 = new SQLStudent(); s1.setSname("student 1"); s1.setSqlTeacher(t); SQLStudent s2 = new SQLStudent(); s2.setSname("student 2"); s2.setSqlTeacher(t); SQLStudent s3 = new SQLStudent(); s3.setSname("student 3"); s3.setSqlTeacher(t); session.save(s1); session.save(s2); session.save(s3); ts.commit(); } finally { session.close(); sf.close(); } } }
代碼下載:https://github.com/shaoyesun/hibernate_study.git