Hibernate事務管理-HibernateTransactionManager-對hibernate session的管理


由於對SSH還停留在比較初級的應用水平上,今天在遇到一個疑惑時折騰了很久,具體問題是這樣的,

有這么一個測試方法,

1     public static void test1() {
2         ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml","daoContext.xml");
3         MgrManager mgr = (MgrManager)ctx.getBean("mgrManager");
4         List<EmpBean> emps = mgr.getEmpsByMgr("weblogic");
5         for (EmpBean empBean : emps) {
6             System.out.println(empBean.getEmpName());
7         }
8     }

其中的MgrManager是一個業務類, 提供一個根據名字查詢員工的功能, 以上方法執行完全沒有問題,

然后又有下面這個測試方法,

    public static void test2() {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml","daoContext.xml");
        EmployeeDao empDao = (EmployeeDao)ctx.getBean("employeeDao");
        Employee emp = empDao.findByName("oracle");
        System.out.println(emp.getSalary());
    }

 

test1是使用業務類間接得查詢數據庫,得到結果,而test2是通過dao直接查詢數據庫, 但是test2始終報錯說沒有數據庫session。

百思不得其解,按理說所有的bean是通過spring管理的,既然spring為業務類注入了sessionFactory, 為何dao類就沒有呢?

然后通過手工在test2中寫了如下代碼,發現是可以通過測試的,

    public static void test3() {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml","daoContext.xml");
        SessionFactory sf = (SessionFactory)ctx.getBean("sessionFactory");
        Session session = sf.openSession();
        List<Employee> emps = session.createQuery("select e from Employee e where e.name = 'oracle'").list();
    }

 

也就是說,問題不在於Spring容器中沒有sessionFactory, 而是sessionFactory沒有被open!那為什么test1的例子中的sessionFaction又open了呢?

看了配置文件半天,發現有這么關鍵的一行配置,

<aop:pointcut id="leePointcut" expression="bean(empManager)||bean(mgrManager))" />

 

另外,通過面向切面編程原理,Spring通過AOP機制為dao對象的數據操作提供事務管理,有如下配置,

<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <!-- 配置詳細的事務語義 -->
    <tx:attributes>
        <!-- 所有以get開頭的方法是只讀的 -->
        <tx:method name="get*" read-only="true" />
        <!-- 其他方法使用默認設置 -->
        <tx:method name="*" />
    </tx:attributes>
</tx:advice>
<aop:config>
<!-- 配置一個切入點,用來匹配empManager和mgrManager兩個Bean的所有方法的執行 -->
<aop:pointcut id="leePointcut" expression="bean(empManager)||bean(mgrManager)||bean(employeeDao)" />
<!-- 指定在leePointcut切入點應用txAdvice事務增強 -->
<aop:advisor advice-ref="txAdvice" pointcut-ref="leePointcut" />
</aop:config>

 

而下面這段配置是用來配置真正的事務管理類, 正是通過上面的切面配置, 將業務類與增強處理關聯起來, 同時通過下面的事務管理類進行事務管理

<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"
    p:sessionFactory-ref="sessionFactory" />

那么重點就在上面的transactionManager這個bean了, 通過查詢資料,初步了解到, HibernateTransactionManager這個類提供 sessionFactory的管理,為了實現數據同步,在HibernateTransactionManager內部會進行Hibernate session的open和close,並將打開的Hibernaate sesion關聯到當前的Application session,在Application中則通過getCurrentSession方式獲取爭取的打開的Hibernate session,  從而解決某些方面的線程安全及同步問題。

由此可見,由於上面配置事務管理的切面類僅僅只是針對了業務類,即默認情況下只有業務類才用於打開的session, 由此可以理解上面的test2為什么報“沒有打開的session”錯誤了。

針對上面的配置, 我做了如下修改,

<bean id="TestManager" class="service.impl.TestManagerImpl" p:empDao-ref="employeeDao"/>

 

果然修改之后test2就能正常執行了。

 

以上僅僅涉及非常非常小的問題, 主要還是對HibernateTransactionManager的理解不夠深入造成的。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM