最近因为要做一个有关Transaction的Knowledge share, 我实现了一个 "Client Owner Transaction" 的sample。 基本原理是根据 Mark Richards article.
基本原理
- 由客户端控制Transaction的start/commit/rollback, Transaction Context将被传到Service Layer。由此可以确保客户端发起的多个invokation都在一个transaction中。
- 这种模式适用于"chatty"的客户端。采用这种方式service layer可以定义fine-grained的接口。
- 实现方式不外乎两种。一种在容器内或者拥有独立的transaction manager的(比如JOTM)。这种方式使用Programmatic的方式,通过JNDI获取JTA的UserTransaction, 由UserTransaction的begin/commit/rollback等Methods来控制transaction。这种方式主要用于EJB。另外一种采用Spring的Transaction annotation。下面的实现要点就是描述了这种方式。
实现要点
主要框架是Spring+struts2+JPA(Hibernate)。 这里的客户端我设定为Action control。Transaction由Struts的Action发起,由Spring控制的Service Class获得Transaction context后执行JPA的EntityManager去做Persistent。
Transaction的控制全部采用Spring Declaritive 的方式。 其中几个要点如下:
1) 将@Transactional 注释放置于Action class,由于Spring是采用AOP来实现Transaction的控制的。而Spring AOP有两种方式,JDK代理和CGLIB。默认方式是JDK代理,这种方式要求被代理的目标类的public method 必须有接口。但是对于Action 的实现类,一般不会为它再去创建一个Interface。如果采用CGLib的方式, 则必须将<aop:aspectj-autoproxy proxy-target-class="true"/>放于spring的配置文件中。
Spring的配置文件如下:
2) 在Service类中,将@Transactional(propagation=Propagation.SUPPORTS)放置于类level或者methods level。