我会辩解说, EJB 有什么样的粒度, Spring 也能提供。
在 jpetstore 示范程序里面, 两个 DAO 对象可以使用不同的datasource, 也就是这样:
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName"><value>java:comp/env/jdbc/jpetstore</value></property>
</bean>
<!-- Additional JNDI DataSource for J2EE environments -->
<!-- Refers to the order database, containing order data -->
<!-- (see dataAccessContext-local.xml for an alternative) -->
<bean id="orderDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName"><value>java:comp/env/jdbc/jpetstore-order</value></property>
</bean>
<bean id="itemDao" class="org.springframework.samples.jpetstore.dao.ibatis.SqlMapItemDao">
<property name="dataSource"><ref local="dataSource"/></property>
<property name="sqlMap"><ref local="sqlMap"/></property>
</bean>
<!-- Refers to the order database here -->
<!-- (see dataAccessContext-local.xml for an alternative) -->
<bean id="orderDao" class="org.springframework.samples.jpetstore.dao.ibatis.SqlMapOrderDao">
<property name="dataSource"><ref local="orderDataSource"/></property>
<property name="sqlMap"><ref local="sqlMap"/></property>
<property name="sequenceDao"><ref local="sequenceDao"/></property>
</bean>
这里面 itemDao 和orderDao 使用不同的 datasource, 这两个datasource 都是由 j2ee 容器配置在 JNDI 中的.
在 petStoreImpl中 有这样一个方法
public void insertOrder(Order order) {
this.orderDao.insertOrder(order);
this.itemDao.updateQuantity(order);
}
现在我们把perStoreImpl 放到一个 SLSB 中, 有三种管理 transaction 的方法:
- CMT (Container Managed Transactions) wrapping the EJB, delegating to a POJO object wrapped with Spring Transactions.
- CMT wrapping the EJB, delegating to a POJO object not wapped with any Spring transactions.
- NO CMT wrapping the EJB, delegating to a POJO object wrapped with Spring TX.
这三种方法都能达到相同的效果: 完成一个跨越数据库的transaction. 实际上Spring 的作者们似乎更倾向于最后一种方案, 也就是不用 CMT 而全部依靠Spring.
在处理分布交易方面, Spring 似乎并无先天局限性. 放在高端 j2ee 容器中, Spring可以使用 容器提供的各种分布式资源, 并正确地完成交易,独立自主地, 或者参与到 CMT 中.