2015年10月31日 星期六

Query、SQLQuery、Criteria 快取 (Hibernate3.x 十一)

前面的一級、二級快取對Query沒有作用,要有另外的設定,我指的Query包括Query、SQLQuery、Criteria,以下都講Query

Query q1 = s.createQuery(hql);
Emp e1 = (Emp) q1.uniqueResult();
System.out.println("e1:" + e1.getEname());
    
Emp e2 = (Emp) s.get(Emp.class, 7369);
System.out.println("e2:" + e2.getEname());

※此時get可以讀到快取,看起來好像ok

Emp e2 = (Emp) s.get(Emp.class, 7369);
System.out.println("e2:" + e2.getEname());
    
Query q1 = s.createQuery(hql);
q1.setCacheable(true);
Emp e1 = (Emp) q1.uniqueResult();
System.out.println("e1:" + e1.getEname());

※但把get放在前面就讀不到了,看起來Query會放到快取裡,所以get讀得到
※但相反後Query無法讀取get的快取,看起來Query不去讀取快取的樣子
※我試Query、Criteria都是這樣的結果,但SQLQuery怎麼放都不行


想讓Query讀得到,必需在hibernate.cfg.xml設定
<property name="hibernate.cache.use_second_level_cache">true</property>
<property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
<property name="hibernate.QueryCacheEnabled">true</property>
    
<property name="hibernate.cache.use_query_cache">true</property>

※前三行是二級快取的設定,後面才是現在要的設定

※這個設定一定要設二級快取,不然執行時會報「org.hibernate.cache.NoCachingEnabledException: Second-level cache is not enabled for usage [hibernate.cache.use_second_level_cache | hibernate.cache.use_query_cache]」的錯,也就是Query只能用二級快取


Session s = HibernateUtil2.getSession();
    
final String sql = "select * from Emp where empno = 7369";
final String hql = "from Emp where empno = 7369";
    
try {
    Query q1 = s.createSQLQuery(sql).addScalar("ename",
            Hibernate.STRING);
    q1.setCacheable(true);
    System.out.println("e1:" + q1.uniqueResult());
    
    Query q2 = s.createSQLQuery(sql).addScalar("ename",
            Hibernate.STRING);
    q2.setCacheable(true);
    System.out.println("e2:" + q2.uniqueResult());
    
    Query q3 = s.createQuery(hql);
    q3.setCacheable(true);
    Emp e3 = (Emp) q3.uniqueResult();
    System.out.println("e3:" + e3.getEname());
    
    Query q4 = s.createQuery(hql);
    q4.setCacheable(true);
    Emp e4 = (Emp) q4.uniqueResult();
    System.out.println("e4:" + e4.getEname());
    
    Criteria q5 = s.createCriteria(Emp.class);
    q5.setCacheable(true);
    q5.add(Restrictions.eq("empno", 7369));
    Emp e5 = (Emp) q5.uniqueResult();
    System.out.println("e5:" + e5.getEname());
    
    Criteria q6 = s.createCriteria(Emp.class);
    q6.setCacheable(true);
    q6.add(Restrictions.eq("empno", 7369));
    Emp e6 = (Emp) q6.uniqueResult();
    System.out.println("e6:" + e6.getEname());
    
    Emp xxx = (Emp) s.get(Emp.class, 7369);
    System.out.println("xxx:" + xxx.getEname());
} catch (Exception e) {
    System.err.println("例外錯誤!");
    e.printStackTrace();
} finally {
    if (s.isOpen()) {
        s.close();
    }
}

※只有設定還不夠,還要在程式寫setCacheable(true),而且每一個Query都要,不然都抓不到快取

※每個快取不能混用,如SQLQuery對SQLQuery、Criteria對Criteria、Query對Query,混用一樣也是抓不到快取

※以第二張圖的程式碼,加上setCacheable(true),還是抓不到快取

沒有留言:

張貼留言