HibernateTemplate還提供了一種更加靈活的方式來操作數據庫,通過這種方式可以完全使用Hibernate的操作方式。HibernateTemplate的靈活訪問方式可通過如下兩個方法完成:
● Object execute(HibernateCallback action)。
● List execute(HibernateCallback action)。
這兩個方法都需要一個HibernateCallback的實例,HibernateCallback實例可在任何有效的Hibernate數據訪問中使用。程序開發者通過HibernateCallback,可以完全使用Hibernate靈活的方式來訪問數據庫,解決Spring封裝 Hibernate后靈活性不足的缺陷。
HibernateCallback 是一個接口,該接口包含一個方法doInHibernate(org.hibernate. Session session),該方法只有一個參數Session。在開發中提供HibernateCallback實現類時,必須實現接口里包含的 doInHibernate方法,在該方法體內即可獲得Hibernate Session的引用,一旦獲得了Hibernate Session的引用,就可以完全以Hibernate的方式進行數據庫訪問。
注意:doInHibernate方法內可以訪問Session,該
Session對象是綁定在該線程的Session實例。該方法內的持久層操作,與不使用Spring時的持久層操作完全相同。這保證了對於復雜的持久層訪問,依然可以使用Hibernate的訪問方式。
下面的代碼對HibernateDaoSupport類進行擴展(雖然Spring 2.0的HibernateTemplate提供了一個分頁方法setMaxResults,但僅此一個方法依然不能實現分頁查詢),這種擴展主要是為該類增加了3個分頁查詢的方法,分頁查詢時必須直接調用Hibernate的Session完成,因此,必須借助於HibernateCallBack的幫助。
public class YeekuHibernateDaoSupport extends HibernateDaoSupport
{
/**
* 使用hql 語句進行分頁查詢操作
* @param hql 需要查詢的hql語句
* @param offset 第一條記錄索引
* @param pageSize 每頁需要顯示的記錄數
* @return 當前頁的所有記錄
*/
public List findByPage(final String hql,
final int offset, final int pageSize)
{
//HibernateDaoSupport已經包含了getHibernateTemplate()方法
List list = getHibernateTemplate().executeFind(new
HibernateCallback()
{
public Object doInHibernate(Session session)
throws HibernateException, SQLException
//該方法體內以Hibernate方法進行持久層訪問
{
List result = session.createQuery(hql)
.setFirstResult(offset)
.setMaxResults(pageSize)
.list();
return result;
}
});
return list;
}
/**
* 使用hql 語句進行分頁查詢操作
* @param hql 需要查詢的hql語句
* @param value 如果hql有一個參數需要傳入,value就是傳入的參數
* @param offset 第一條記錄索引
* @param pageSize 每頁需要顯示的記錄數
* @return 當前頁的所有記錄
*/
public List findByPage(final String hql , final Object value ,
final int offset, final int pageSize)
{
List list = getHibernateTemplate().executeFind(new
HibernateCallback()
{
public Object doInHibernate(Session session)
throws HibernateException, SQLException
{
//下面查詢的是最簡單的Hiberante HQL查詢
List result = session.createQuery(hql)
.setParameter(0, value)
.setFirstResult(offset)
.setMaxResults(pageSize)
.list();
return result;
}
});
return list;
}
/**
* 使用hql 語句進行分頁查詢操作
* @param hql 需要查詢的hql語句
* @param values 如果hql有多個參數需要傳入,values就是傳入的參數數組
* @param offset 第一條記錄索引
* @param pageSize 每頁需要顯示的記錄數
* @return 當前頁的所有記錄
*/
public List findByPage(final String hql, final Object[] values,
final int offset, final int pageSize)
{
List list = getHibernateTemplate().executeFind(new
HibernateCallback()
{
public Object doInHibernate(Session session)
throws HibernateException, SQLException
{
Query query = session.createQuery(hql);
for (int i = 0 ; i < values.length ; i++)
{
query.setParameter( i, values[i]);
}
List result = query.setFirstResult(offset)
.setMaxResults(pageSize)
.list();
return result;
}
});
return list;
}
}
在上面的代碼實現中,直接使用了getHibernateTemplate()方法,這個方法由Hibernate- DaoSupport提供。而YeekuHibernateDaoSupport是HibernateDaoSupport的子類,因此,可以直接使用該方法。
當實現doInHibernate(Session session)方法時,完全以Hibernate的方式進行數據庫訪問,這樣保證了Hibernate進行數據庫訪問的靈活性。
注意:Spring提供的XxxTemplate和XxxCallBack互為補充,二者體現了
Spring框架設計的用心良苦:XxxTemplate對通用操作進行封裝,而XxxCallBack解決了封裝后靈活性不足的缺陷。
