在接觸HibernateTemplate之前,我們知道,在對數據庫進行CRUD操作之前,需要開啓session、transaction等等。在hibernate學習過程中,我們知道了,得到session之前,需要先得到SessionFactory,進而從SessionFactory裏面openSession(),或者getCurrentSession(),接着開啓一transaction,然後進行對數據庫的操作,在操作結束後,提交事務,關閉session。當然如果session是通過getCurrentSession()得到的話,不用我們手動關閉。還有,關於異常的處理,這就涉及到事務的回滾。我們發現,這樣邏輯的代碼我們需要反覆使用,每次session的歷程都是這樣的。實例代碼如下:
- public class HibernateCoreAPITest {
- private static SessionFactory sessionFactory;
- @BeforeClass
- public static void beforeClass() {
- sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
- }
- @AfterClass
- public static void afterClass() {
- sessionFactory.close();
- }
- @Test
- public void testTeacherSave() {
- Teacher t = new Teacher();
- t.setName("t1");
- t.setTitle("middle");
- t.setBirthDate(new Date());
- //Session session = sessionFactory.openSession();
- Session session = sessionFactory.getCurrentSession();
- session.beginTransaction();
- session.save(t);
- session.getTransaction().commit();
- }
HibernateTemplate
從上面測試用的代碼(省略了異常處理和事務回滾)來看,如果在業務層某部分的功能模塊比較多,那我們不得不老實重複關於session的代碼。爲避免這樣的窘境,於是有了HibernateTemplate的出現。
給HibernateTemplate注入SessionFactory,我們就能獲得利用SessionFactory來create sessionFactory,進而進行所有關於sessionFactory的功能操作。同時,由於HibernateTemplate本身關於sessionFactory的處理原理,我們不再需要手動編寫關於sessionFactory、session、transaction等等代碼。我們只需要編寫關於業務邏輯相關的操作,其他的一併由HibernateTemplate完成。HibernateTemplate的這種設計模式我們稱之爲TemplateMethod,採用的方式叫callback或者鉤子函數。這裏的重點就是把SessionFactory注入到HibernateTemplate裏面!!!
- <span style="font-size:18px;">@Component("employeeDao")
- public class EmployeeDaoImpl implements EmployeeDao {
- private HibernateTemplate hibernateTemplate;
- public HibernateTemplate getHibernateTemplate() {
- return hibernateTemplate;
- }
- @Resource
- public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
- this.hibernateTemplate = hibernateTemplate;
- }
- @Override
- public void save(Employee employee) {
- hibernateTemplate().save(employee);
- }</span>
上面的代碼採用的是annotation方式,當然我們也可以使用xml方式,一樣很簡單。
HibernateDaoSupport
HibernateDaoSupport對於HibernateTemplate,就好比HibernateTemplate對於SessionFactory,兩兩的關係,大致雷同。只是這一次,HibernateDaoSupport是需要被繼承的,而且不能像後者那樣減少什麼的代碼量。就是把HibernateTemplate注入到HibernateDaoSupport裏面,當然把SessionFactory注入到HibernateDaoTemplate裏面一樣可以。而起由於在HibernateDaoSupport裏面set方法是final類型的,我們不能夠重寫該方法,所以就不能過通過annotation方式注入HibernateTemplate,只有採用xml方式。
- <span style="font-size:18px;"><bean id="employeeDao" class="com.zzw.dao.impl.EmployeeDaoImpl">
- <property name="hibernateTemplate" ref="hibernateTemplate"></property>
- </bean></span>
- <span style="font-size:18px;">public class EmployeeDaoImpl extends HibernateDaoSupport implements EmployeeDao {
- @Override
- public void save(Employee employee) {
- this.getHibernateTemplate().save(employee);
- }
- @Override
- public void delete(Employee employee) {
- this.getHibernateTemplate().delete(employee);
- }
- @Override
- public void update(Employee employee) {
- this.getHibernateTemplate().update(employee);
- }</span>
接着,我們來談談HibernateDaoSupport的拓展,當多個***Dao需要注入繼承HibernateDaoSupport的時候,理所當然,我們得在applicationContext.xml裏面給每個Dao注入hibernateTemplate或者sessionFactory。少量的好說,但是如果很多,比如幾百個Dao(當然,這種情況我們很少遇到,我們假設這樣),這樣,由於採用的是xml方式,我們配置起來一樣顯得麻煩。這個時候,我們可以這樣解決,抽象一個頂層Dao類,這個類必須注入HibernateTemplate,其實這個注入了HibernateTemplate的頂層Dao類,他的功能類似於HibernateDaoSupport類,唯一的不同就是這個類裏面的set方法是我們自己定義的,不是final類型的,所以我們採用註解annotation方式注入HibernateTemplate。然後,讓那些***Dao繼承這個頂層Dao類。這樣在xml裏面不用編寫任何的註解配置,當然除了在HibernateTemplate裏面注入sessionFactory。
注入HibernateTemplate的頂層Dao類:SuperDao.java
- <span style="font-size:18px;">import javax.annotation.Resource;
- import org.springframework.orm.hibernate3.HibernateTemplate;
- import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
- import org.springframework.stereotype.Component;
- @Component
- public class SuperDAO {
- private HibernateTemplate hibernateTemplate;
- public HibernateTemplate getHibernateTemplate() {
- return hibernateTemplate;
- }
- @Resource
- public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
- this.hibernateTemplate = hibernateTemplate;
- }
- }</span>
衆多***Dao裏面的一實例:UserDao.java
- <span style="font-size:18px;">@Component("userDAO")
- public class UserDAOImpl extends SuperDAO implements UserDAO {
- public void save(User user) {
- this.getHibernateTemplate().save(user);
- }
- }</span>
從上面的代碼中,我們發現整個過程我們並沒有使用HibernateDaoSupport這個抽象類,而是使用一個它的替代類:由我們自己定義的。如果非得使用HibernateDaoSupport類的話,也可以,就是講頂層Dao類SuperDao改爲:
- <span style="font-size:18px;">@Component
- public class SuperDAO extends HibernateDaoSupport {
- @Resource(name="hibernateTemplate")
- public void setSuperHibernateTemplate(HibernateTemplate hibernateTemplate) {
- super.setHibernateTemplate(hibernateTemplate);
- }
- }
- </span>
注意:spring容器在對子類進行初始化的時候,首先會將其父類進行初始化,而如果兩者的注入方式不一致,比如一個是xml方式,一個是annotation方式的話,很容易出錯,所以,最好使用同種注入方式!
最後,溫馨提示:建議使用HibernateTemplate的annotation注入方式,即第二種哦,親!