準備工作和三十四篇一樣
三十三篇有工具可以使用Criteria,看第一張圖就可以了,使用方法我試了好久,如下:
※一定要在ⓒ或ⓒ的子項按右鍵-->Hibernate Criteria Editor,然後畫面的右邊才會自動出現一些相關的語法,但語法不一定可以Run,像我的是修改後的結果
※我寫
java.util.List l = session.createCriteria(vo.Emp.class).list();
l.size();
也是可以,但如果跑迴圈就掛了,研究中…知道的回應一下吧!這個官網也寫的不是很清楚,網路上也很少人在討論這個
※這裡還有jboss的教學影片,第二個「Edit and run HQL/JPA-QL queries」和第三個「Criteria Editor in Action」有介紹
Session s = HibernateUtil2.getSession(); Transaction tx = s.beginTransaction(); try { Criteria criteria = s.createCriteria(Emp.class); // ProjectionList plist = Projections.projectionList(); // plist.add(Projections.rowCount()); // plist.add(Projections.avg("sal")); // plist.add(Projections.groupProperty("dept")); // criteria.setProjection(plist); criteria.setProjection( Projections.projectionList() .add(Projections.rowCount()) .add(Projections.avg("sal")) .add(Projections.groupProperty("dept")) ); @SuppressWarnings("unchecked") List<Object[]> list = criteria.list(); for (Object[] oA : list) { for (Object o : oA) { if(o instanceof Dept){ Dept d = (Dept)o; System.out.println(d.getDname()); } else { System.out.println(o); } } } } catch (Exception e) { tx.rollback(); System.err.println("例外錯誤!"); e.printStackTrace(); } finally { if (s.isOpen()) { s.close(); } }
※Criteria (Hibernate3.x 七)的最後一個匯總函數,這時因為是一對多,所以Emp.java沒有deptno關聯字段,這時只要指定集合就會幫我們關聯了
※註解的部分是較慢速的寫法
※sqlRestriction
Criteria cri = s.createCriteria(Emp.class); cri.add(Restrictions.sqlRestriction( "{alias}.sal between ? and ?", new Object[] { 1500d, 3000d }, new Type[] { StandardBasicTypes.DOUBLE, StandardBasicTypes.DOUBLE })); // Hibernate.STRING; @SuppressWarnings("unchecked") List<Emp> list = cri.list(); System.out.println(list.size()); for (Emp e : list) { System.out.println(e.getEname()); }
※這是個overloading,共有三種,看API即可知道
※註解的Hibernate.STRING已經過時了,要用StandardBasicTypes
※?的個數、順序,對應第二個參數,第三個參數的型態對應第二個參數
※加上{alias},控制台會有from後面有「this_」,不加就沒有,可是不知道加這個有什麼用,我不加還是很正常的執行
※Property.forName
Criteria cri = s.createCriteria(Emp.class); cri.add(Property.forName("sal").between(1500d, 3000d));
※結果和上面一樣
※createAlias
Criteria cri = s.createCriteria(Emp.class); cri.createAlias("dept", "d"); cri.add(Restrictions.eq("d.deptno", 20)); // eqProperty
※dept是Emp的一方,如果有多個一方,可以用xxProperty
※Criteria.ALIAS_TO_ENTITY_MAP
Criteria cri = s.createCriteria(Emp.class); cri.createAlias("dept", "d"); cri.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP); @SuppressWarnings("unchecked") List<Map<String, Object>> list = cri.list(); for (Map<String, Object> m : list) { Emp e = (Emp) m.get(Criteria.ROOT_ALIAS); System.out.println(e.getSal()); System.out.println(e.getDept().getDname()); Dept d = (Dept) m.get("d"); System.out.println(d.getDeptno() + "\n"); }
※配合Criteria.ROOT_ALIAS可以關聯createAlias的別名
※FetchMode
Criteria cri = s.createCriteria(Emp.class); cri.setFetchMode("dept", FetchMode.JOIN); // FetchMode.EAGER 已廢棄 @SuppressWarnings("unchecked") List<Emp> list = cri.list(); System.out.println(list.size()); for (Emp e : list) { System.out.println(e.getEname()); }
※FetchMode的EAGER和LAZY已廢棄,要用JOIN和SELECT,這個功能可以忽略設定檔的fetch設定
※Example
※範例一
Emp emp = new Emp(); emp.setJob("clerk"); Criteria cri = s.createCriteria(Emp.class); cri.add(Example.create(emp).ignoreCase()); @SuppressWarnings("unchecked") List<Emp> list = cri.list(); System.out.println(list.size()); for (Emp e : list) { System.out.println(e.getEname()); }
※使用Example.create(),然後裝進Criteria
※範例二
Emp emp = new Emp(); emp.setJob("s"); Example example = Example.create(emp); example.excludeProperty("comm"); example.ignoreCase(); example.enableLike(MatchMode.START); Criteria cri = s.createCriteria(Emp.class); cri.add(example); @SuppressWarnings("unchecked") List<Emp> list = cri.list(); System.out.println(list.size()); for (Emp e : list) { System.out.println(e.getEname()); }
※MatchMode有四種
xxx就是上面的s
.EXACT:xxx,也就是沒有like,enableLike()裡面不放參數也是EXACT,繼然都不用了,所以enableLike都不打也是一樣
.START:xxx%
.END:%xxx
.ANYWHERE:%xxx%
※Example還有excludeNone()、excludeZeroes(),就是where條件必需是0、null的
※DetachedCriteria
離線查詢可以在session外面創建一個查詢,然後使用隨面一個session來執行DetachedCriteria dcri = DetachedCriteria.forClass(Emp.class); dcri.add(Property.forName("sal").ne(3000d)); Criteria cri = dcri.getExecutableCriteria(s).setMaxResults(5); @SuppressWarnings("unchecked") List<Emp> list = cri.list(); System.out.println(list.size()); for (Emp e : list) { System.out.println(e.getEname()); }
※控制台訊息:
select
*
from
( select
欄位
from
schema.Emp this_
where
this_.SAL<>?
)
where
rownum <= ?
※子查詢
DetachedCriteria avgSal = DetachedCriteria.forClass(Emp.class); avgSal.setProjection(Property.forName("sal").avg()); Criteria cri = s.createCriteria(Emp.class) .add(Property.forName("sal").gt(avgSal)); //.add(Subqueries.geAll(2500d, avgSal)); //.add(Subqueries.exists(avgSal.setProjection(Projections.property("sal"))));
※控制台訊息:
select
欄位
from
schema.Emp this_
where
this_.SAL > (
select
avg(this_.SAL) as y0_
from
C##SCOTT.Emp this_
)
※另外兩個註解的訊息是
...
where
? >= all (
...
)
和
...
where
exists (
...
)
※自然identifier查詢
官方的意思是說,使用快取時常失效且效能太低,它說使用這種方式查詢會比較快首先使用<natural-id>將想查詢的屬性包起來,這裡是將ename和job包起來
<id> ... </id> <natural-id> <property name="ename" type="java.lang.String" length="4"> <column name="ENAME" length="4" /> </property> <property name="job" type="java.lang.String"> <column name="JOB" /> </property> </natural-id> <property> ... </property>
然後用Restrictions.naturalId()並開啟二級快取
Criteria cri = s.createCriteria(Emp.class); NaturalIdentifier ni = Restrictions.naturalId(); ni.set("ename", "SMITH"); ni.set("job", "CLERK"); cri.add(ni).setCacheable(true); @SuppressWarnings("unchecked") List<Emp> list = cri.list(); System.out.println(list.size()); for (Emp e : list) { System.out.println(e.getSal()); }
※開啟二級快取可看第九篇
※我試的結果,不管有沒有開啟二級快取或者用<natural-id>都查的到,至於有沒有比較快,我是沒什麼感覺啦!應該是資料太少了吧!
沒有留言:
張貼留言