日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

【转】深入分析@Transactional的用法

發布時間:2023/12/13 综合教程 33 生活家
生活随笔 收集整理的這篇文章主要介紹了 【转】深入分析@Transactional的用法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

關鍵詞:事務, 編程式事務,聲明式事務、spring 事務管理、AOP事務增強、@Transactional

在分析深入分析@Transactional的使用之前,我們先回顧一下事務的一些基本內容。

事務的基本概念

先來回顧一下事務的基本概念和特性。數據庫事務(Database Transaction) ,是指作為單個邏輯工作單元執行的一系列操作,要么完全地執行,要么完全地不執行。事務,就必須具備ACID特性,即原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)和持久性(Durability)。

編程式事務與聲明式事務

Spring與Hibernate的整合實現的事務管理是常用的一種功能。Hibernate 建議所有的數據庫訪問都應放在事務內進行,即使只進行只讀操作。事務又應該盡可能短,因為長事務會導致長時間無法釋放表內行級鎖,從而降低系統并發的性能。 Spring 同時支持編程式事務和聲明式事務。

編程式事務需要在代碼中顯式調用beginTransaction()、commit()、rollback()等事務管理相關的方法。Spring 的聲明式事務管理在底層是建立在 AOP 的基礎之上的,其本質是對方法前后進行攔截,然后在目標方法開始之前創建或者加入一個事務,在執行完目標方法之后根據執行情況提交或者回滾事務。事務增強也是AOP的一大用武之處。

使用聲明式事務

聲明式事務最大的優點就是不需要通過編程的方式管理事務,這樣就不需要在業務邏輯代碼中摻雜事務管理的代碼,只需在配置文件中做相關的事務規則聲明,很好的分離了業務邏輯和事務管理邏輯。以spring+jpa整合增加聲明式事務為例,下面是使用聲明式事務的配置方式以及使用。

applicationContext.xml配置

<!-- 配置entityManagerFactory 配置 -->

<bean id="entityManagerFactory"class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">

<property name="dataSource" ref="dataSource" />

<property name="persistenceXmlLocation"value="/WEB-INF/classes/persistence.xml" />

<property name="loadTimeWeaver">

<beanclass="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" />

</property>

</bean>

<!-- 配置聲明式事務管理,使用JpaTransactionManager作為事務管理器的實現類 –>

<bean id="transactionManager"class="org.springframework.orm.jpa.JpaTransactionManager">

<property name="entityManagerFactory" ref="entityManagerFactory" />

</bean>

<!--聲明業務組件使用注解生成事務代理 -->

<tx:annotation-driven transaction-manager="transactionManager" />

使用@Transactional配置聲明式事務管理

在spirng 的配置文件中配置了事務管理和注解驅動之后,我們就可以在業務層使用@Transactional 配置聲明式事務管理了。如下

@Service

@Transactional

public class BaseService<T> implements IBaseService<T> {

@Autowired

private IBaseDao<T> baseDao;

......

}

@Transactional深入使用

上面我們已經知道了聲明式事務管理的用法了,下面我們將進一步分析@Transactional在各種場景下用法。

事務的傳播行為

@Transactional注解支持9個屬性的設置,其中Propagation屬性用來枚舉事務的傳播行為。所謂事務傳播行為就是多個事務方法相互調用時,事務如何在這些方法間傳播。Spring 支持 7 種事務傳播行為:

REQUIRED 是常用的事務傳播行為,如果當前沒有事務,就新建一個事務,如果已經存在一個事務中,加入到這個事務中。其它傳播行為大家可另查閱。

多個事務方法的嵌套調用時的事務傳播

有三個事務方法調用嵌套關系如下:

PayHisInfoService.update()->PayHisInfoService.save()->PayInfoService.update()

@Transactional(propagation=Propagation.REQUIRED)

public abstract classBaseService<E>{

public abstract List<E> findAll();

}

@Component

public class PayHisInfoService extends BaseService<PayHisInfo>{

@Resource

private PayHisInfoDao payHisInfoDao;

@Resource

private PayInfoService payInfoService;

public voidupdate(PayHisInfo payHisInfo,PayInfo payInfo){

save(payHisInfo);

payInfoService.update(payInfo);

}

public intsave(PayHisInfo payHisInfo){

return payHisInfoDao.insert(payHisInfo);

}

}

@Component

public class PayInfoService extends BaseService<PayInfo>{

@Resource

private transient PayInfoDao payInfoDao;

@Override

@Transactional(propagation=Propagation.SUPPORTS, readOnly=true)

public List<PayInfo> findAll() {

return payInfoDao.findAll();

}

public intupdate(PayInfo payInfo){

return payInfoDao.update(payInfo);

}

}

當我們按照上面的調用嵌套關系執行時,結果如下

從日志中我們可以看出,PayHisInfoService.update()執行時開啟了一個事務,而PayHisInfoService.save()方法和PayHisInfoService.update()方法處于同一個類中,調用時沒有發生事務傳播,就像已經處于PayHisInfoService.update()方法的事務當中一樣。而當執行PayInfoService.update()時,提示“Participating in existing transaction”,這說明發生了事務傳播,即PayInfoService.update()并沒有新建一個事務,而是加入到已有的PayHisInfoService.update()事務中。

多線程環境下的事務傳播

現在我們將上面例子中的PayHisInfoService.update()用另一個線程來執行,如下

@Component

public class PayHisInfoService extends BaseService<PayHisInfo>{

@Resource

private PayHisInfoDao payHisInfoDao;

@Resource

private PayInfoService payInfoService;

public void update(PayHisInfo payHisInfo,PayInfo payInfo){

save(payHisInfo);

//payInfoService.update(payInfo);

PayInfoThread pifth = new PayInfoThread(payInfoService,payInfo);

pifth.start();

}

public int save(PayHisInfo payHisInfo){

return payHisInfoDao.insert(payHisInfo);

}

private class PayInfoThread extends Thread{

private PayInfoService payInfoService;

private PayInfo payInfo;

private PayInfoThread(PayInfoService payInfoService,PayInfo payInfo) {

this.payInfoService = payInfoService;

this.payInfo = payInfo;

}

public void run() {

System.out.println("PayInfoThread updating payInfo...");

payInfoService.update(payInfo);

}

}

}

當我們按照上面的調用嵌套關系執行時,結果如下

從日志結果可以看出,在執行PayHisInfoService.update()和PayInfoService.update()時分別創建了各自的事務。而PayHisInfoService.save()和PayHisInfoService.update()則在同一個線程中執行。所以spring 的事務管理是線程安全的。

在相同線程中進行相互嵌套調用的事務方法工作于相同的事務中。如果這些相互嵌套調用的方法工作在不同的線程中,不同線程下的事務方法工作在獨立的事務中。

@Transactional的繼承關系

或許你已經在上面的例子中看出了,我們只在父類BaseService中聲明了@Transactional,子類就自然得到事務增強。注解并沒有繼承這種說法,但此處用“繼承關系”來形容父類@Transactional和子類方法之間的關系最恰當不過了:父類Service聲明了@Transactional,子類繼承父類,父類的聲明的@Transactional會對子類的所有方法進行事務增強。這個還有個很實用的用法,例如測試基類繼承

AbstractTransactionalJUnit4SpringContextTests

聲明@Transactional可方便進行事務測試

@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration("/applicationContext.xml")

@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)

@Transactional

public class BaseTest extends AbstractTransactionalJUnit4SpringContextTests {

public Object getBean(String beanName){

return applicationContext.getBean(beanName);

}

}

給BaseTest 聲明了@Transactional了之后,就會自動給我們自己編寫的測試類中的所有測試方法進行事務增強。

@Transactional的優先級

如果子類的方法重寫了父類的方法并且聲明了@Transactional,那么子類的事務聲明會優先于父類的事務聲明。

利用spring的AOP進行事務切面增強

還是上面的列子,把父類聲明的@Transactional去掉。在applicationContext.xml中配置事務增強切面,配置如下:

<!--②使用aop和tx命名空間語法為PayHisInfoService所有公用方法添加事務增強 -->

<aop:config proxy-target-class="true">

<aop:pointcut id="serviceJdbcMethod"

expression="execution(public * com.xxx.service.PayHisInfoService.*(..))"/>

<aop:advisor pointcut-ref="serviceJdbcMethod" advice-ref="jdbcAdvice" order="0"/>

</aop:config>

<tx:advice id="jdbcAdvice" transaction-manager="transactionManager">

<tx:attributes>

<tx:method name="*"/>

</tx:attributes>

</tx:advice>

運行測試用例,結果如下:

當有一條數據更新失敗時,事務會自動回滾,如下:

@Transactional方法的可見度

上面為了測試演示方便,我們把@Transactional都聲明在了類上。實際上@Transactional可以作用于接口、接口方法、類以及類方法上。但是 Spring 小組建議不要在接口或者接口方法上使用該注解,因為這只有在使用基于接口的代理時它才會生效。另外,@Transactional 注解應該只被應用到 public 方法上,這是由Spring AOP的本質決定的(從上面的Spring AOP 事務增強可以看出,就是針對方法的)。如果你在 protected、private 或者默認可見性的方法上使用 @Transactional 注解,這將被忽略,也不會拋出任何異常。

總結

(1)聲明式事務優于編程式事務

(2)事務方法的嵌套調用會產生事務傳播

(3)spring 的事務管理是線程安全的

(4)父類的聲明的@Transactional會對子類的所有方法進行事務增強

(5)從Spring AOP本質看,@Transactional 注解應該只被應用到 public 方法上

參考文檔

http://www.ibm.com/developerworks/cn/java/j-lo-spring-ts3/

http://www.ibm.com/developerworks/cn/education/opensource/os-cn-spring-trans/

作者:ITPSC
出處:http://www.cnblogs.com/hjwublog/

總結

以上是生活随笔為你收集整理的【转】深入分析@Transactional的用法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。