準備工作和三十四篇一樣
三十三篇有工具可以使用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>都查的到,至於有沒有比較快,我是沒什麼感覺啦!應該是資料太少了吧!

沒有留言:
張貼留言