在上一篇文章中介绍了事务的基本概念,包括事务的ACID性质,以及事务的类型并且稍微提到了事务划分。
对于任何一个需要持久化数据的应用而言,事务划分(Transaction Demarcation)的规划都是非常重要的一环。如果规划的不好,轻则影响性能,重则会导致在某些情况下数据发生不一致,从而严重影响业务逻辑的顺利进行。
本文继续介绍事务划分在当前JavaEE技术体系下基于EJB的实现方案。虽然EJB算是JavaEE的亲儿子,但是它的境遇却不怎么好,主要是被EJB 2.x给坑过的开发人员都对他失去了兴趣。加上同时代兴起的Spring Framework等轻量级的JavaEE解决方案,就算到了如今EJB 3.x时代,各方面都进步了不少,但还是有不少人拿有色眼睛看待它的。不过,作为JavaEE的正统,还是有必要看看它是如何处理事务划分这一问题的。
事务划分概要
Resource-local事务类型
在上文中我们已经知道Resource-local事务类型实际上就是直接建立在JDBC标准的中的DataSource接口之上的一种事务类型,它直接建立在底层数据库所支持的事务之上,因此十分底层。而在往常的JDBC编程中,这是最常用的一种方式,正因为它的抽象层次低,需要开发人员百分百地控制事务的划分,使用代码指定事务的开始结束等生命周期。随着JavaEE标准的诞生,以及Web开发大行其道,出现的应用服务器(Application Server)则在最底层的基于DataSource接口的事务模型之上抽象出来基于Container的事务类型,这也是当今JavaEE开发中最常见,也是最常用的一种事务类型。下文即将讨论的都属于Container事务的范畴。
Container事务类型
在这种事务类型中,由于应用服务器提供的容器对事务提供了一定程度的支持,因此有下面两种实现思路:
- 在容器的帮助下完成自动划分
- 使用JTA接口在应用中编码完成显式划分
EJB中的事务划分
回顾了一下事务划分是什么,下面开始正式介绍EJB是如何处理事务划分的。
容器管理的事务(Container-Managed Transaction, CMT)
首先,在EJB中默认的事务划分实现方式就是基于容器管理的事务(CMT)。所以你什么都不指定,那么就会默认使用CMT了。当然也可以显式指定:
@Stateful