1、在action中获取UserTransaction,并调用UserTransaction.begin()方法;
2、调用sessionbean1和sessionbean2的方法;
3、调用UserTransaction.commit/rollback完成事务。
2、调用sessionbean1和sessionbean2的方法;
3、调用UserTransaction.commit/rollback完成事务。
问题一:
在action中通过手动获取UserTransaction,sessionbean1和sessionbean2事务管理方式为BMT对吗?问题二:
如果通过spring将UserTransaction注入到action中,配置文件如何写?问题三:
如果我不想通过UserTransaction手动控制事务的边界,即我想用CMT,又该如何做?谢谢
在action中通过手动获取UserTransaction,sessionbean1和sessionbean2事务管理方式为BMT对吗?BMT和CMT基本都是针对service/ejb而言的,事务管理一般也都在Service层/ejb上控制,Action/jsp/servlet等前段程序无所谓BMT/CMT,如果需要跨多个service/ejb,就需要使用UserTransaction。此时,被调用的ejb(如你所说sessionbean1/sessionbean2)/service仍然属于CMT。问题二:
如果通过spring将UserTransaction注入到action中,配置文件如何写? <bean id="transactionManager" class="...TransactionManagerImpl" />
<bean id="userTransaction" class="...UserTransactionImpl" />
<bean id="jtaTransactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="userTransaction" ref="userTransaction" />
<property name="transactionManager" ref="transactionManager" />
</bean>
<tx:annotation-driven transaction-manager="jtaTransactionManager" />类似如上这样,然后通过ApplicationContext.getBean("userTransaction")获取即可。问题三:
如果我不想通过UserTransaction手动控制事务的边界,即我想用CMT,又该如何做?如果你的操作在ejb/service里的话,是可以的。直接标注一下事务属性为Required,容器就帮你管理事务了。但看你的描述你的操作在Action中,Action里容器是无法管理事务的,如果你希望事务跨两个service/ejb,可以尝试:1)通过UserTransaction;2)将跨两个service/ejb的操作提取出来,放在一个新的ejb/service中。
首先非常感谢您的帮助,谢谢您耐心的回答在问题二中:
<bean id="transactionManager" class="...TransactionManagerImpl" />
<bean id="userTransaction" class="...UserTransactionImpl" />TransactionManagerImpl和UserTransactionImpl这两个实现类是自己写得吗?
<tx:annotation-driven transaction-manager="jtaTransactionManager" />这句话起什么作用?
为什么不用指定数据源?
在问题三中:
“将跨两个service/ejb的操作提取出来,放在一个新的ejb/service中”首先看一下结构图:我无法将在不同机器上的多个session bean注入到本地的session bean中(在图中,session bean3和session bean 4注入到sessionbean1中),该怎么处理能顺利注入?另外,这种情况下,肯定会涉及到分布式事务,我使用的是<datasources>
<xa-datasource>类型的数据源,在不同机器上分别放置了oracle-xa-ds.xml,但事务并不起作用。
我想知道,这几台服务器上的数据源文件是不是应该一模一样?具体怎么配置?再把我的oracle-xa-ds.xml附上:
<?xml version="1.0" encoding="UTF-8"?>
<datasources>
<xa-datasource>
<jndi-name>MyOracleDS</jndi-name>
<isSameRM-override-value>false</isSameRM-override-value>
<xa-datasource-class>oracle.jdbc.xa.client.OracleXADataSource</xa-datasource-class>
<!--服务器249 -->
<xa-datasource-property name="URL">jdbc:oracle:thin:@192.168.24.249:1521:ORCL</xa-datasource-property>
<xa-datasource-property name="User">gxpt1</xa-datasource-property>
<xa-datasource-property name="Password">gxpt1</xa-datasource-property>
<exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.OracleExceptionSorter</exception-sorter-class-name>
<no-tx-separate-pools/>
<metadata>
<type-mapping>Oracle9i</type-mapping>
</metadata>
</xa-datasource>
<xa-datasource>
<jndi-name>JcOracleDS</jndi-name>
<isSameRM-override-value>false</isSameRM-override-value>
<!--服务器252 -->
<xa-datasource-class>oracle.jdbc.xa.client.OracleXADataSource</xa-datasource-class>
<xa-datasource-property name="URL">jdbc:oracle:thin:@192.168.24.252:1521:ORCL</xa-datasource-property>
<xa-datasource-property name="User">gxpt1</xa-datasource-property>
<xa-datasource-property name="Password">gxpt1</xa-datasource-property> <exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.OracleExceptionSorter</exception-sorter-class-name>
<no-tx-separate-pools/>
<metadata>
<type-mapping>Oracle9i</type-mapping>
</metadata>
</xa-datasource>
<mbean code="org.jboss.resource.adapter.jdbc.vendor.OracleXAExceptionFormatter"
name="jboss.jca:service=OracleXAExceptionFormatter">
<depends optional-attribute-name="TransactionManagerService">jboss:service=TransactionManager</depends>
</mbean></datasources>
首先非常感谢您的帮助,谢谢您耐心的回答在问题二中:
<bean id="transactionManager" class="...TransactionManagerImpl" />
<bean id="userTransaction" class="...UserTransactionImpl" />TransactionManagerImpl和UserTransactionImpl这两个实现类是自己写得吗?
这个是事务管理器,如果在spring里使用分布式事务管理器需要自行指定,不过不一定要自己写,网上有不少开源的jta实现,如jotm。(本人刚新开了一个openjta的项目,如果有兴趣可以关注一下,哈哈http://code.google.com/p/openjta),不过如果你用jboss的话,就完全就不必使用spring来管理事务了。如果要获取UserTransaction的话直接通过jndi来lookup就行。。<tx:annotation-driven transaction-manager="jtaTransactionManager" />这句话起什么作用?
这个配置告诉spring容器根据注解的事务属性来控制事务,并告知spring容器事务管理器。为什么不用指定数据源?
可能你之前使用DataSourceTransactionManager比较多,所以觉得需要指定数据源。一般来说,事务管理器没法指定数据源,因为参与事务的数据源可能会有0~n个(DataSourceTransactionManager只支持一个数据源所以才可以指定)。如果在spring用JtaTransactionManager的话,一般是在数据源中指定事务管理器。
在问题三中:
“将跨两个service/ejb的操作提取出来,放在一个新的ejb/service中”首先看一下结构图:我无法将在不同机器上的多个session bean注入到本地的session bean中(在图中,session bean3和session bean 4注入到sessionbean1中),该怎么处理能顺利注入?远程Ejb一般只能通过lookup获得吧我之前的意思是你可以将服务器c中的sessionbean1和sessionbean2组合到一个新的sessionbean0中(sessionbean0仍然部署在服务器c中,sessionbean0的操作与你现在在action中的操作相同) ,然后你在action中调用sessionbean0,这样action就只调用一个sessionbean了。另外,这种情况下,肯定会涉及到分布式事务,我使用的是<datasources>
<xa-datasource>类型的数据源,在不同机器上分别放置了oracle-xa-ds.xml,但事务并不起作用。
我想知道,这几台服务器上的数据源文件是不是应该一模一样?具体怎么配置?再把我的oracle-xa-ds.xml附上:
<?xml version="1.0" encoding="UTF-8"?>
<datasources>
<xa-datasource>
<jndi-name>MyOracleDS</jndi-name>
<isSameRM-override-value>false</isSameRM-override-value>
<xa-datasource-class>oracle.jdbc.xa.client.OracleXADataSource</xa-datasource-class>
<!--服务器249 -->
<xa-datasource-property name="URL">jdbc:oracle:thin:@192.168.24.249:1521:ORCL</xa-datasource-property>
<xa-datasource-property name="User">gxpt1</xa-datasource-property>
<xa-datasource-property name="Password">gxpt1</xa-datasource-property>
<exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.OracleExceptionSorter</exception-sorter-class-name>
<no-tx-separate-pools/>
<metadata>
<type-mapping>Oracle9i</type-mapping>
</metadata>
</xa-datasource>
<xa-datasource>
<jndi-name>JcOracleDS</jndi-name>
<isSameRM-override-value>false</isSameRM-override-value>
<!--服务器252 -->
<xa-datasource-class>oracle.jdbc.xa.client.OracleXADataSource</xa-datasource-class>
<xa-datasource-property name="URL">jdbc:oracle:thin:@192.168.24.252:1521:ORCL</xa-datasource-property>
<xa-datasource-property name="User">gxpt1</xa-datasource-property>
<xa-datasource-property name="Password">gxpt1</xa-datasource-property> <exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.OracleExceptionSorter</exception-sorter-class-name>
<no-tx-separate-pools/>
<metadata>
<type-mapping>Oracle9i</type-mapping>
</metadata>
</xa-datasource>
<mbean code="org.jboss.resource.adapter.jdbc.vendor.OracleXAExceptionFormatter"
name="jboss.jca:service=OracleXAExceptionFormatter">
<depends optional-attribute-name="TransactionManagerService">jboss:service=TransactionManager</depends>
</mbean></datasources>
jboss服务器我用的不多,这么具体配置,我也看不出啥问题来
架构方面大致是这样的---
web客户端用得是:spring+struts底层业务逻辑用得是:ejb通过spring,将远程ejb sessionbean注入struts控制的action中。------用到现在,我也感觉有些不伦不类了,不知道我表达得是否清晰。
我按照你说的方式,做了如下demo--
我在一个ejb sessionbean(A)中,需要注入远程的session bean(B)和远程的session bean(C),代码如下:
@Stateless
@Remote( ISessionBeanA.class)
@TransactionManagement(TransactionManagementType.CONTAINER)
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public class SessionBeanA implements ISessionBeanA {
@Resource(mappedName = "SessionBeanB/Remote")
private ISessionBeanB sessionBeanB;
@Resource(mappedName = "SessionBeanC/Remote")
private ISessionBeanC sessionBeanC; @Override
public void addOrder(Order order) {
sessionBeanB.save(order.getBasicinfo());
sessionBeanC.save(order.getClient());
}
如上代码,我该如何注入sessionBeanB和sessionBeanC?
我试过加入jndi文件:
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.provider.url=192.168.24.249,192.168.24.252sessionBeanB在192.168.24.249上部署着,sessionBeanC在192.168.24.252上部署着。按上述配置,sessionBeanB注入成功,sessionBeanC输入失败。
如果将jndi中java.naming.provider.url=192.168.24.249,192.168.24.252改为
java.naming.provider.url=192.168.24.252,192.168.24.249,则sessionBeanC注入成功,sessionBeanB注入失败。如果sessionBeanA,sessionBeanB和sessionBeanC在一个服务器上,那么能注入成功,没有问题,但现在条件不允许我将他们拿到一个机器上来。谢谢您耐心为解答。