spring提供訪問數據庫的有三種方式:
?
HibernateDaoSupport
HibernateTemplate(推薦使用)
jdbcTemplate(我們一般不用)
?
類所在包:
HibernateTemplate:org.springframework.orm.hibernate3.HibernateTemplate
HibernateDaoSupport:org.springframework.orm.hibernate3.support.HibernateDaoSupport
?
? ? ? ?spring如果想整合hibernate的話,首先就應該獲得SessionFactory這個類,然后再通過獲得session就可以進行訪問數據庫了,即spring提供的類HibernateDaoSupport,HibernateTemplate應該是有setSessionFactory,在使用的時候注入一下就可以了。HibernateTemplate類中的方法是spring封裝了hibernate中的方法,在使用完了以后會自動釋放session。而如果使用了HibernateDaoSupport的getSession方法,就需要配套的用releaseSession(Session?session)或者session.close來關閉session,無法實現自動管理session。所以很多人都傾向于用spring的?Hibernatetemplate類或者HibernateDaoSupport的getHibernateTemplate方法來實現實現數據庫的交互,當然,如果遇到hibernatetemplate無法實現的功能,可以使用?HibernateDaoSupport。
?
首先我們先來看一下HibernateTemplate類:
首先我們來說一下我們為什么要用HibernateTemplate,其實這個類就是我們平常使用hibernate進行dao操作的一個模版,我們不需要那些開頭的開啟事務、獲得session,結尾的提交事務,關閉session等操作了,這些工作是HibernateTemplate都給我們封裝好了,我們直接調用其dao的操作方法就可以了,并且他還給我們封裝了hibernate的幾乎所有的異常,這樣我們在處理異常的時候就不要記住那么多繁瑣的異常了。所以我們就叫他是一個hibernate中dao操作的模版,他提供的常用方法:
get?從數據庫相關表中獲取一條記錄并封裝返回一個對象(Object)?
load?作用與get基本相同,不過只有在對該對象的數據實際調用時,才會去查詢數據庫?
save?添加記錄?
saveOrUpdate?判斷相應記錄是否已存在,據此進行添加或修改記錄
update?修改記錄?
delete?刪除記錄??
?
下面我們來看一下HibernateTemplate的源碼來看一下他的具體方法是怎么樣實現的,其實你觀察源碼可以發現,他所提供的方法幾乎都是一個實現實現的。下面我們就以save方法來具體看一下:
?
?
- public?Serializable?save(final?Object?entity)?throws?DataAccessException?{??
- return?(Serializable)?executeWithNativeSession(new?HibernateCallback()?{??
- public?Object?doInHibernate(Session?session)?throws?HibernateException?{??
- checkWriteOperationAllowed(session);??
- return?session.save(entity);??
- }??
- });}??
?
? ? ? ?我們從源碼中可以發現,HibernateTemplate把我們hibernate的異常都封裝成了一個DataAccessException?。好了,解釋一下上面的代碼,上面代碼中主要是調用了executeWithNativeSession這個方法,其實這個方法就是給我們封裝好的hibernate開頭和結尾一些列操作,他需要一個參數,這個參數是一個回調的對象,其實這個對象是實現了一個HibernateCallback的接口,實現這個接口需要實現這個接口里面的方法doInHibernate,這個方法需要把當前的session傳遞過來,其實他就是把他原先模版里獲得的session傳過去。然后在在doInHibernate中利用模版中得到的session進行保存數據。其實我們調用save的過程就是給他傳一個回調對象的過程,我們可以看到,他的回調對象是new出來的。
?
?????如果你還沒看懂的話,那大家來看一下下面我們實現自己的HibernateTemplate,他的思路和spring提供的基本是一樣的:其中MyHibernateCallback?是一個簡單接口:
?
- import?org.hibernate.Session;??
- public?class?MyHibernateTemplate?{??
- public?void?executeWithNativeSession(MyHibernateCallback?callback)?{??
- Session?s?=?null;??
- try?{??
- s?=?getSession();??
- s.beginTransaction();??
- callback.doInHibernate(s);??
- s.getTransaction().commit();??
- }?catch?(Exception?e)?{??
- s.getTransaction().rollback();??
- }?finally?{??
- //...??
- }??
- }??
- private?Session?getSession()?{??
- //?TODO?Auto-generated?method?stub??
- return?null;??
- }??
- public?void?save(final?Object?o)?{??
- new?MyHibernateTemplate().executeWithNativeSession(new?MyHibernateCallback()?{??
- public?void?doInHibernate(Session?s)?{??
- s.save(o);??
- }??
- });??
- }??
- }??
?
?
? ? 好了,原理我們介紹完了之后,下面我們來看一下具體應用,這個HibernateTemplate在我們的程序中怎么用,在上面我們也說過了,這個用法主要是把sessionfactory注入給我們的HibernateTemplate
首先我們來看一下beans.xml的配置:
?
?
- <?xml?version="1.0"?encoding="UTF-8"?>??
- <beans?xmlns="http://www.springframework.org/schema/beans"??
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"??
- xmlns:context="http://www.springframework.org/schema/context"??
- xmlns:aop="http://www.springframework.org/schema/aop"??
- xmlns:tx="http://www.springframework.org/schema/tx"??
- xsi:schemaLocation="http://www.springframework.org/schema/beans??
- ???????????http://www.springframework.org/schema/beans/spring-beans-2.5.xsd??
- ???????????http://www.springframework.org/schema/context??
- ???????????http://www.springframework.org/schema/context/spring-context-2.5.xsd??
- ???????????http://www.springframework.org/schema/aop??
- ???????????http://www.springframework.org/schema/aop/spring-aop-2.5.xsd??
- ???????????http://www.springframework.org/schema/tx???
- ???????????http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">??
- <bean?id="dataSource"??
- class="org.apache.commons.dbcp.BasicDataSource"??
- destroy-method="close">??
- <property?name="driverClassName"?value="com.mysql.jdbc.Driver"?/>??
- <property?name="url"?value="jdbc:mysql://localhost:3306/spring"?/>??
- <property?name="username"?value="root"?/>??
- <property?name="password"?value="bjsxt"?/>??
- </bean>??
- <bean?id="sessionFactory"??
- class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">??
- <property?name="dataSource"?ref="dataSource"?/>??
- <property?name="annotatedClasses">??
- <list>??
- <value>com.bjsxt.model.User</value>??
- <value>com.bjsxt.model.Log</value>??
- </list>??
- </property>??
- <property?name="hibernateProperties">??
- <props>??
- <prop?key="hibernate.dialect">??
- org.hibernate.dialect.MySQLDialect??
- </prop>??
- <prop?key="hibernate.show_sql">true</prop>??
- </props>??
- </property>??
- </bean>??
- <bean?id="hibernateTemplate"?class="org.springframework.orm.hibernate3.HibernateTemplate">??
- <property?name="sessionFactory"?ref="sessionFactory"></property>??
- </bean>??
- <bean?id="UserDao"?class="com.bzu.dao.userDao">??
- <property?name="hibernateTemplate"?ref="hibernateTemplate"></property>??
- </bean>??
- </beans>??
?
下一步我們來看一下hibernateTemplate的使用:
?
- public?class?UserDAOImpl?implements?UserDAO?{??
- private?HibernateTemplate?hibernateTemplate;??
- public?HibernateTemplate?getHibernateTemplate()?{??
- return?hibernateTemplate;??
- }??
- public?void?setHibernateTemplate(HibernateTemplate?hibernateTemplate)?{??
- this.hibernateTemplate?=?hibernateTemplate;??
- }??
- public?void?save(User?user)?{??
- hibernateTemplate.save(user);??
- }}??
?
這基本上就是我們的hibernateTemplate原理及使用了,其實他的使用很簡單
?
下面,我們來看一下HibernateDaoSupport:
通過上面我們可以看出,通過xml注入hibernateTemplate,我們可以想象的到所有DAO類中都會有HibernateTemplate的bean方法,于是上面hibernateTemplate的set、get的方法和xml配置會有大量的,于是就出現了代碼冗余和重復,我們怎么才能避免這個重復呢,我們很容易應該能想到,把上面注入hibernateTemplate抽出一個類,然后讓我們的dao類來繼承這個類。不過這個類Spring已經有了,那就是HibernateDaoSupport,除此之外,HibernateDaoSupport也有SessionFactory的bean方法,所以我們在用HibernateDaoSupport的時候同樣也要給我們注入sessionfactory或者hibernateTemplate,在用的時候你會發現HibernateDaoSupport也給我們提供了getHibernateDaoSupport方法。
相關配置示例:userdao繼承了HibernateDaoSupport
?
?
- <bean?id="userdao"?class="com.bzu.dao.uerdao">??
- <property?name="sessionFactory"?ref="sessionFactory"></property>??
- </bean>??
?
?
? ? ?用上面的方法我們可以發現一個問題,我們同樣解決不了xml配置重復的問題,我們每一個dao都要在xml注入sessionfactory或者hibernateTemplate,解決這個問題的辦法就是我們自己在抽出一個SuperDao類,讓這個類去繼承HibernateDaoSupport,然后我們給SuperDao類去配置,這樣的話,我們在我的dao類中直接去繼承SuperDao類就可以了,這樣不管有多少dao類,只要繼承SuperDao,我們就可以實現我們想要的功能了。