學習SSH框架記錄片4----Spring 宣告式事務整合 Hibernate
1.配置事務管理器
1-1. XML配置示例
<bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
1-2. 說明
1> 類 HibernateTransactionManager 在 spring-orm-4.3.5.RELEASE.jar 包中,選中對應的 Hibernate 版本即可
2> 屬性中配置該事務管理器所用到的 Bean,即類 LocalSessionFactoryBean
2.配置事務屬性,需要事務管理器
2-1. XML配置示例
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="get*" read-only="true" />
<tx:method name="purchase" propagation="REQUIRES_NEW"/>
<tx:method name="*" />
</tx:attributes >
</tx:advice>
2-2. 說明
1> 使用 <tx>
節點需要引入 tx 的 XML 名稱空間
2> 屬性 transaction-manager 指定了 事務管理器
3> 節點 <tx:attributes>
是事務屬性集合
4> 節點 <tx:method>
指定具體的事務屬性,可配置傳播行為、隔離級別、超時、異常回滾等屬性
5> 屬性 name 指定方法名稱,可使用萬用字元
6> propatation 指定事務傳播行為,預設值為 REQUIRED,表示使用當前事務,而 REQUIRES_NEW 表示使用新事務
3.配置事務切點,並把切點和事務屬性關聯起來
3-1. XML配置示例
<aop:config>
<aop:pointcut expression="execution(* com.test.spring.hibernate.service.*.*(..))"
id="txPointcut" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut" />
</aop:config>
3-2. 說明
1> 使用 <aop>
節點需要引入 aop 的 XML 名稱空間
2> 節點 <aop:pointcut>
用於配置切點
3> 屬性 expression 用於指定連線點,其中萬用字元 【*】 可表示【許可權訪問修飾符、返回值型別、類名、方法名】,而 .【..】表示任意引數
4> 節點 <aop:advisor>
用於關聯切點和事務
5> 屬性 advice-ref 指定引用的事務,pointcut-ref 指定引用的切點
4.綜合理解
4-1. 配置事務屬性
如上所述,就是為了滿足一些業務需求,配置不同的屬性資訊。
4-2. 配置事務切點
例如,上面的方法 purchase 是一個連線點,這樣的話,在執行切點方法時,Spring 的事務管理器會自動呼叫事務相關的方法,開啟事務,提交事務等,因為這個切面是 Spring 提供的,所以我們只需要關聯一下即可,若是日誌、異常之類的切面,則需要自己開發相關類,並在其中指定切點。
5.注意事項
5-1. 如果註釋掉 <aop>
相關的配置,則報異常
org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread
at org.springframework.orm.hibernate5.SpringSessionContext.currentSession(SpringSessionContext.java:133)
t org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:456)
5-2. 原因
在事務開始之前,獲取 Session,然後和執行緒繫結,再由 SessionFactory.getCurrentSession() 得到與執行緒繫結的 Session,因為註釋掉了事務和切點的關聯,執行切點對應的方法時,也就不會啟用事務,從而也不會執行 Session 和當前執行緒繫結的操作,導致呼叫 getCurrentSession() 方法時報異常。