Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在单独的EJB方法中启动/结束事务_Java_Database_Ejb_Cluster Computing_Bean Managed Transactions - Fatal编程技术网

Java 在单独的EJB方法中启动/结束事务

Java 在单独的EJB方法中启动/结束事务,java,database,ejb,cluster-computing,bean-managed-transactions,Java,Database,Ejb,Cluster Computing,Bean Managed Transactions,我开发了一个典型的企业应用程序,负责将客户配置到第三方系统。该系统有一个限制,即只有一个线程可以在某个客户上工作。因此,我们添加了一个简单的锁定机制,它由@Singleton组成,其中包含当前正在进行的客户ID集。每当有新的资源调配请求出现时,它都会首先检查此集。如果cusotomerId存在,它将等待,否则它会将其添加到集合并进入处理 最近决定将此应用程序部署在集群中,这意味着此锁定方法不再有效。我们提出了一个使用DB进行锁定的解决方案。我们创建了一个包含CustomerID的单列表(它还有一

我开发了一个典型的企业应用程序,负责将客户配置到第三方系统。该系统有一个限制,即只有一个线程可以在某个客户上工作。因此,我们添加了一个简单的锁定机制,它由
@Singleton
组成,其中包含当前正在进行的
客户ID集。每当有新的资源调配请求出现时,它都会首先检查此
。如果cusotomerId存在,它将等待,否则它会将其添加到
集合
并进入处理

最近决定将此应用程序部署在集群中,这意味着此锁定方法不再有效。我们提出了一个使用DB进行锁定的解决方案。我们创建了一个包含CustomerID的单列表(它还有一个唯一的约束)。当一个新的配置请求到来时,我们启动一个事务,并尝试用
选择更新
锁定customerId行(如果customerId尚不存在,则插入它)。在这之后,我们开始为客户配置,完成后,我们提交事务。
概念可行,但我在交易方面有问题。目前,我们有一个类
CustomerLock
,其中包含
add()
remove()
方法,用于在
集合中添加和删除customerID。我想将这个类转换成一个具有bean管理事务的无状态EJB
add()
方法将启动事务并锁定行,而
remove()
方法将提交事务并因此解锁行。但似乎事务的开始和结束必须以相同的方法进行。是否有一种方法可以使用我描述的方法,或者我必须修改逻辑以便事务以相同的方法开始和结束

CustomerLock类别:

@Stateless
@TransactionManagement(TransactionManagementType.BEAN)
public class CustomerLock {

    @Resource
    private UserTransaction tx;

    public void add(String customerId) throws Exception {
        try {
            tx.begin();
            dsApi.lock()
        } catch (Exception e) {
            throw e;
        }
    }

    public void remove(String customerId) throws Exception {
        try {
            tx.commit();
        } catch (Exception e) {
            throw e
        }
    }
}
CustomerProvisioner类摘录:

public abstract class CustomerProvisioner {

    ...

    public void execute(String customerId) {
        try {
            customerLock.add(customerId);

            processing....

            customerLock.remove(customerId);
        } catch (Exception e) {
            logger.error("Error", e);
        }
    }

    ...

}
StandardCustomerProvisioner类别:

@Stateless
public class StandardCustomerProvisioner extends CustomerProvisioner {

    ...

    public void provision(String customerId) {
        // do some business logic
        super.execute(customerId);
    }
}

正如@Gimby所指出的,您不应该混合使用容器管理的事务和bean管理的事务。由于您的StandardCustomerProvision没有类似“@TransactionManagement(TransactionManagementType.BEAN)”的注释,因此它使用容器管理的事务,并且默认情况下是必需的

您有两个选项可以让它工作:

1) 要删除带有UserTransaction调用的“@TransactionManagement(TransactionManagementType.BEAN)”并运行CMT


2) 将此注释(@TransactionManagement(TransactionManagementType.BEAN)”添加到StandardCustomerProvisioner并使用此方法的事务标记调用,以便所有调用的方法使用相同的事务上下文。无论如何都应该删除来自CustomerLock的标记调用。

为什么您认为“事务的开始和结束必须在同一个方法中发生”?在finally block BTW中有一个非常奇怪的提交调用。当一切正常时(没有抛出异常),它将提交事务,DB锁将消失(它是事务范围的)。抱歉。。。“finally”没有出现:)我更正了代码。这些代码通常不够详细。什么是“客户提供”?另一个EJB?它有点“扭曲”,但从技术上讲是的。再详细一点。。。我们有三个CustomerProvisioning抽象类的实现。现在我唯一能看到的是容器管理的事务和bean管理的事务混合在一起,但我根本看不到它们是如何连接在一起的。很抱歉,响应太晚了。。。是的,我完全误解了这个事务在容器中的工作方式。只有在几句评论之后,我才开始思考如何实现上述解决方案。我想我只是需要一点“头脑风暴”:)谢谢大家的回复!干杯