※Scalar查詢
Session s = HibernateUtil2.getSession(); Transaction tx = s.beginTransaction(); try { final String sql = "SELECT * FROM EMP WHERE SAL >= :sal"; System.out.println("方法一"); SQLQuery q1 = s.createSQLQuery(sql); q1.setInteger("sal", 3000); @SuppressWarnings("unchecked") List<Object[]> list1 = q1.list(); for (Object[] oA : list1) { for (Object o : oA) { System.out.println(o); } System.out.println(); } System.out.println("=============\n方法二"); SQLQuery q2 = s.createSQLQuery(sql); q2.setInteger("sal", 3200); q2.addScalar("DEPTNO", StandardBasicTypes.INTEGER); q2.addScalar("COMM", StandardBasicTypes.STRING); q2.addScalar("HIREDATE", StandardBasicTypes.DATE); @SuppressWarnings("unchecked") List<Object[][]> list2 = q2.list(); for (Object[] oA : list2) { for (Object o : oA) { System.out.println(o); } System.out.println(); } } catch (Exception e) { tx.rollback(); System.err.println("例外錯誤!"); e.printStackTrace(); } finally { if (s.isOpen()) { s.close(); } }
※Entity查詢
final String sql = "SELECT * FROM EMP WHERE SAL >= :sal"; SQLQuery q = s.createSQLQuery(sql); q.setInteger("sal", 3000); q.addEntity(Emp.class); @SuppressWarnings("unchecked") List<Emp> list = q.list(); for (Emp e : list) { System.out.println(e.getEname()); System.out.println(e.getDept().getDname() + "\n"); }
※如果不用「*」,就會出「java.sql.SQLException: 資料欄名稱無效」的錯,所以應該只能全部,我試過每一個欄位都打或多幾個名稱一樣的欄位也是可以的,但少了就是不行
final String sql = "SELECT e.*, d.* FROM EMP e, DEPT d WHERE e.SAL >= :sal"; SQLQuery q = s.createSQLQuery(sql); q.setInteger("sal", 3000); q.addEntity("e", Emp.class); q.addEntity("d", Dept.class); @SuppressWarnings("unchecked") List<Object[]> list = q.list(); for (Iterator<Object[]> it = list.iterator(); it.hasNext();) { Emp emp = (Emp) it.next()[0]; Dept dept = (Dept) it.next()[1]; System.out.println(emp.getEname()); System.out.println(dept.getDname() + "\n"); } // for (Object[] oA : list) { // for (Object o : oA) { // if (o instanceof Emp) { // Emp emp = (Emp) o; // System.out.println(emp.getEname()); // } else if (o instanceof Dept) { // Dept dept = (Dept) o; // System.out.println(dept.getDname()); // } // } // System.out.println(); // }
※多個Entity就對應好別名即可
※註解的部分是另一種撈值的方法,比較好理解
※處理關聯和集合
final String sql = "SELECT e.*, d.* FROM EMP e, DEPT d WHERE e.DEPTNO = d.DEPTNO AND e.SAL >= :sal"; SQLQuery q = s.createSQLQuery(sql); q.setInteger("sal", 3000); q.addEntity("e", Emp.class); q.addJoin("d", "e.dept"); @SuppressWarnings("unchecked") List<Object[]> list = q.list(); for (Iterator<Object[]> it = list.iterator(); it.hasNext();) { Object[] obj = it.next(); Emp emp = (Emp) obj[0]; Dept dept = (Dept) obj[1]; System.out.println(emp.getEname()); System.out.println(dept.getDname() + "\n"); }
※addJoin至少要兩個參數,官方這章節我覺得寫錯的地方很多
※回傳多個Entity
final String sql = "SELECT {e1.*}, {e2.*} FROM EMP e1, EMP e2 WHERE e1.MGR = e2.EMPNO"; SQLQuery q = s.createSQLQuery(sql); q.addEntity("e1", Emp.class); q.addEntity("e2", Emp.class); @SuppressWarnings("unchecked") List<Object[]> list = q.list(); for (Object[] obj : list) { Emp emp1 = (Emp) obj[0]; Emp emp2 = (Emp) obj[1]; System.out.println(emp1.getEname()); System.out.println(emp2.getEname() + "\n"); }
※官方的意思是說e1和e2如果有相同的名稱,就必須用「{}」包起來,否則會出錯,但我把它拿掉還是可以,官網也有說是某些資料庫才會,可能是oracle不會吧!或許版本有差也說不定
但不加addEntity就真的會出錯了,訊息是「未支援 SQL92 符號的位置」,還有要加「{}」就全加,不然就全不加,否則會出「java.sql.SQLException: 資料欄名稱無效」的錯
※官方還有個表,連結往下一點會看到alias injection names,就是「ID as {c.id}」這種東西,我試不出來,譬如說我下SELECT SAL as {e1.sal}, {e2.*} FROM EMP e1, EMP e2 WHERE e1.MGR = e2.EMPNO,
會出「ORA-00918: 資料欄的定義不明確」的錯,因為前面的Entity查詢的addEntity方法本來就要select全部啊!所以我就把全部的欄位都打出來,但還是一樣的錯,不知道它是怎麼使用的
最後我還新增一張沒外鍵的表,hibernate也不做一對x,但結果也是不行
※回傳非管理的Entity
也就是不經過xml的mapping就可以取得資料庫的值
EmpDept.java
public class EmpDept { private String ooo; private String dname; // setter/getter... }
測試類
final String sql = "SELECT e.ename ooo, d.dname FROM EMP e, DEPT d WHERE e.SAL >= :sal"; SQLQuery q = s.createSQLQuery(sql); q.setInteger("sal", 3000); q.addScalar("ooo", StringType.INSTANCE); q.addScalar("dname", StringType.INSTANCE); q.setResultTransformer(Transformers.aliasToBean(EmpDept.class)); @SuppressWarnings("unchecked") List<EmpDept> list = q.list(); for (Iterator<EmpDept> it = list.iterator(); it.hasNext();) { EmpDept empDept = it.next(); System.out.println(empDept.getOoo() + "\n"); }
※如果不加addScalar的話,會出「Could not find setter for OOO on class EmpDept」的錯,所以我將vo改成大寫就OK了,看來可能是資料庫幫我轉大寫了
※如果不想加addScalar,但vo又想使用依java命名慣例,使用小寫這時可以用:
e.ename \"ooo\", d.dname \"dname\",就就是用「"」包起來,但前後已經有「"」了,所以只好再加個跳脫字元「\」,最後就變成了「\"」
「'」我試過了,不行
※參數
和HQL一樣都有支援「?」和「:varName」如:SELECT * FROM EMP WHERE ENAME like ?
SELECT * FROM EMP WHERE ENAME like :xxx
然後用Query.setXXX,?從0開始,和jdbc一樣;而xxx就對應好就可以了
沒有留言:
張貼留言