DAO開發
注:
(1)以下兩者都需在Spring XML配置文件中,注冊Bean(實現類)來依賴注入SessionFactory.
(2.1)Spring 中進行事務管理的通常方式是利用AOP(面向切片編程)的方式,為普通java類封裝事務控制,它是通過動態代理實現的,由于接口是
延遲實例化的, spring在這段時間內通過攔截器,加載事務切片。原理就是這樣,具體細節請參考jdk中有關動態代理的文檔。本文主要講解
如何在spring中進行事務控制。
(2.2)動態代理的一個重要特征是,它是針對接口的,所以我們的DAO要通過動態代理來讓spring接管事務,就必須在DAO前面抽象出一個接口. 當然
如果沒有這樣的接口,那么spring會使用CGLIB來解決問題,但這不是spring推薦的方式.
(一)直接使用Hibernate API
(不推薦使用)
public class DaoImp implate Dao{
private SessionFactory sessionFactory;
private static String hql = "from User u where u.username=? ";
public void setSessionFactory(SessionFactory sessionFactory){
this.sessionFactory=sessionFactory;
}
public boolean isValidUser(String username) {
try{
List userList = sessionFactory.getCurrentSession().creatQuery(hql).setParameter(0,username).list();
if (userList.size() > 0) {
return true;
} catch (HibernateException ex){
throw converHibernaterAccessException(ex);
}
}
}
優點:與Spring框架完全分離
缺點:(1)無法使用Spring框架封裝所提供的額外功能.如,直接使用Hibernate API 需用try...catch()處理HibernateException異常.
(2)需在實現類中加入setSessionFactory(SessionFactory sessionFactory)屬性,接收依賴注入的SessionFactory.
(二)繼承 Spring 的 HibernateDaoSupport 使用 HibernateTemplate
(不推薦使用getSession())
public class DaoImp extend HibernateDaoSupport implates Dao{
//private SessionFactory sessionFactory;
private static String hql = "from User u where u.username=? ";
//public void setSessionFactory(SessionFactory sessionFactory){
// this.sessionFactory=sessionFactory;
//}
public boolean isValidUser(String username) {
// try{
// List userList = sessionFactory.getCurrentSession().creatQuery(hql).setParameter(0,username).list();
List userList = getHibernateTemplate().find(hql,username);
if (userList.size() > 0) {
return true;
// } catch (HibernateException ex){
// throw converHibernaterAccessException(ex);
// }
}
public boolean isValidUser(String username,String password) throw DataAccessException {
Session session = getSession(); //不推薦使用,用完后需手動關閉
String[] userlist=new String[2];
userlist[0]=username;
userlist[1]=password;
try{
List userList =
session.find(hql,userlist);
//Hibernate語句;
session.close();
if (userList.size() > 0) {
return true;
} catch (HibernateException ex){
throw converHibernaterAccessException(ex);
}
}
}
特點:對HibernateTemplate沒有提供的功能,可以直接調用HibernateDaoSuppor對象的
getSession()方法(極其不推薦使用)得到Session對象實例用try{ Hibernate API }catch (HibernateException ex )操作.
(三)對 HibernateTemplate 沒有提供的功能, 還可以用HibernateCallback 回調的方法管理數據庫.
(極其推薦)
/**
* 使用 hql 語句進行操作
* @param hql HSQL 查詢語句
* @param offset 開始取數據的下標
* @param length 讀取數據記錄數
* @return List 結果集
*/
public List getListForPage ( final String hql , final int offset , final int length ) {
List list = getHibernateTemplate().executeFind ( new HibernateCallback ( ) {
public Object doInHibernate ( Session session ) throws HibernateException, SQLException {
Query query = session.createQuery ( hql ) ;
query.setFirstResult ( offset ) ;
query.setMaxResults ( length ) ;
List list = query.list ( ) ;
return list ;
}
}) ;
return list ;
}
//---------------------------------------------------------------------------
final String queryString = "from Fourm"; //必須定義final類型
List l= getHibernateTemplate().executeFind(new HibernateCallback(){
public Object doInHibernate ( Session session ) throws HibernateException, SQLException {
Query query = session.createQuery ( queryString ) ;
query.setFirstResult ( 0 ) ;
query.setMaxResults ( 10 ) ;
List list = query.list ( ) ;
return list ;
}
//------------------------------------------------------------
為什么不使用getSession(),而使用回調的詳細說明:
紫蝶∏飛揚↗
聽個SPRING+HIBERNATE開發的問題.
SPRING想調用HIBERNATE的方法有兩種,一種是使用getSession();一種是:HibernateCallback回調.
他們有什么不同?
海綿♂寶寶
前者沒有事務管控,Spring把Hibernate最原始的Session給你!但是它不被聲明式事務管理的服務!
紫蝶∏飛揚↗
...聲明式事務不會對他進行事務管理?
海綿♂寶寶
后者也是把Session返給你,但是通過閉包回調的形式給你使用,Spring會在給你之前做一下手腳,例如:添加聲明式事務管理中聲明的事務屬性!
海綿♂寶寶
因為你寫的方法通過匿名函數閉包,然后由Spring去負責執行閉包體內的方法!
海綿♂寶寶
Java里的借口回調基本都是借用匿名內部類實現的閉包!
海綿♂寶寶
你看一下Spring的HibernateDaoSupport的源代碼就知道運行過程了!
海綿♂寶寶
直接使用getSession()還不享有Spring提供的模板支持,也就是說你得手動關閉連接,否則會一直掛在那兒,直到超時連接池才會回收這個連接!
海綿♂寶寶
這樣很容器連接池連接數量溢出!你懂了啊?
紫蝶∏飛揚↗
嗯.
紫蝶∏飛揚↗
new HibernateCallback(){
public Object doInHibernate ( Session session ) throws HibernateException, SQLException {
必須這樣的方式嗎?
海綿♂寶寶
建議補習一下編程中的閉包、回調的知識,再看看Spring的那段代碼就可以徹底理解了!
海綿♂寶寶
恩!
紫蝶∏飛揚↗
哦.明白了.
海綿♂寶寶
如果你覺得getHibernateTemplate()提供的方法不足以滿足你的要求!你就得這么使用!
紫蝶∏飛揚↗
明白.不夠用的情況下用回調.
海綿♂寶寶
閉包JavaScript支持的比較好,因為它是以函數為單元的,Java過于強調面向對象,所以只能用匿名內部類來有限的支持閉包!標準的回調都是方法回調,也就是閉包到方法中,而不是類中!所以Java中的閉包和其他的語言有一些區別的,例如訪問外部變量必須是final的!
海綿♂寶寶
據說JDK1.7會加入對函數閉包調用的支持!
紫蝶∏飛揚↗
...歷害.
紫蝶∏飛揚↗
偶只知道這樣用,不知道為什么這樣用.
海綿♂寶寶
那可不行啊!呵呵!我最一開始也不大明白,后來仔細研究了閉包、回調的知識就懂了!
其實這種用法在Swing編程里天天都用啊!把一個匿名的監聽器實現類注冊到事件源,只不過那個時候沒有注意到這是閉包和回調罷了!
紫蝶∏飛揚↗
看來有時間得好好看看了...
posted on 2007-11-23 11:30
紫蝶∏飛揚↗ 閱讀(5982)
評論(0) 編輯 收藏 所屬分類:
Spring 、
Hibernate