gpt4 book ai didi

java - 彼此有 2 个本地事务(在不同的数据源上)

转载 作者:太空宇宙 更新时间:2023-11-04 06:35:42 25 4
gpt4 key购买 nike

我遇到交易问题。我有一种方法,需要从一个数据源读取数据,将其写入另一个数据源,然后提交到已读取数据的第一个数据源。 (第一个数据源中的数据位于队列中,我需要提交以将它们从队列中删除)。

如果我们有全局 JTA 事务,我就不会担心这个问题,但我们没有。由于架构原因,我们只能使用本地事务。 (我不是建筑师)

这是我所做的(简化):

@Transactional(value="tx1", propagation=REQUIRES_NEW)
public void copy() {
try {
Data data = read();
service.write(data);
} catch (Exception x) {...}
}

服务.java:

@Transactional(value="tx2", propagation=REQUIRES_NEW)
public void write(Data data) {
...
}

我知道当队列上的提交失败时我遇到了问题,因为我已经写入了数据。但这不是问题。这不是这个问题的一部分。

问题是,我收到以下错误:

2014.08.21 12:29:54 INFO : 21.08.2014 12:29:54 org.springframework.transaction.IllegalTransactionStateException: Pre-bound JDBC Connection found! JpaTransactionManager does not support running within DataSourceTransactionManager if told to manage the DataSource itself. It is recommended to use a single JpaTransactionManager for all transactions on a single DataSource, no matter whether JPA or JDBC access.
at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:311)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:371)
at sun.reflect.GeneratedMethodAccessor50.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:309)
at org.springframework.osgi.service.importer.support.internal.aop.ServiceInvoker.doInvoke(ServiceInvoker.java:58)
at org.springframework.osgi.service.importer.support.internal.aop.ServiceInvoker.invoke(ServiceInvoker.java:62)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:131)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionIntercept [StdOut]
2014.08.21 12:29:54 INFO : or.java:119)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.osgi.service.util.internal.aop.ServiceTCCLInterceptor.invokeUnprivileged(ServiceTCCLInterceptor.java:56)
at org.springframework.osgi.service.util.internal.aop.ServiceTCCLInterceptor.invoke(ServiceTCCLInterceptor.java:39)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.osgi.service.importer.support.LocalBundleContextAdvice.invoke(LocalBundleContextAdvice.java:59)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:131)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:119)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at com.sun.proxy.$Proxy797.getTransaction(Unknown Source)
at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:335)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:105)
at org.springframewo [StdOut]
2014.08.21 12:29:54 INFO : rk.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at com.sun.proxy.$Proxy655.write(Unknown Source)

我是不是做了不该做的事?有人对我应该采取哪些不同的做法有好的建议吗?

最佳答案

这只是线索(未经测试),但太长,不适合评论。

您应该首先确保错误确实是由 2 个 @Transactional 注解方法的级联引起的,方法是首先使它们独立(请参阅我上面的评论)。对于帖子的以下内容,我认为这是真的。

您可以尝试使用显式编程事务管理,希望您对 Spring 的要求越少,副作用就越少。

// Beans to be injected
PlatformTransactionManager tx1;
PlatformTransactionManager tx2;
TransactionDefinition td1 = new ;
TransactionDefinition td2;

SessionFactory sf1;
SessionFactory sf2;

// method using explicit transactions
public void copy(Serializable id) throws Exception {
TransactionStatus status1 = tx1.getTransaction(td1);
try {
Session session1 = sf1.getCurrentSession();
Object data = session1.get("Entity", id);
TransactionStatus status2 = tx2.getTransaction(td1);
try {
Session session2 = sf2.getCurrentSession();
session2.saveOrUpdate(data);
}
catch (Exception e2) {
tx2.rollback(status2);
throw e2;
}
tx2.commit(status2);
}
catch (Exception e1) {
tx1.rollback(status1);
throw e1;
}
tx1.commit(status1);
}

但是因为 HibernateTransactionManager javadoc 中的这句话:JTA(通常通过 JtaTransactionManager)对于访问同一事务中的多个事务资源是必要的。在这种情况下,Hibernate 使用的 DataSource 需要启用 JTA(请参阅容器设置),我不确定它是否可以在 JTA 之外工作。

另一个解决方案:根据那 2 个帖子 Distributed transactions in Spring, with and without XAImplementing Spring ChainedTransactionManager according to the “best efforts 1PC” pattern ,您还可以使用 spring-data-common 中的 ChainedTransactionManager

摘自第一篇文章:

ChainedTransactionManager 的配置

<bean id="transactionManager" class="com.springsource.open.db.ChainedTransactionManager">
<property name="transactionManagers">
<list>
<bean
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<bean
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="otherDataSource" />
</bean>
</list>
</property>
</bean>

...请记住,资源的顺序很重要。它们是嵌套的,提交或回滚的发生顺序与它们登记的顺序(即配置中的顺序)相反

但我仍然不确定它是否可以在 JTA 之外工作......

如果这些线索都没有成功,您将不得不再次询问您的系统架构师是否不能选择 JTA。

关于java - 彼此有 2 个本地事务(在不同的数据源上),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25424420/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com