gpt4 book ai didi

java - @Transactional(propagation = Propagation.REQUIRES_NEW)打开两个交易?

转载 作者:行者123 更新时间:2023-12-03 12:59:30 25 4
gpt4 key购买 nike

我们发生了一个生产事件,导致一堆线程陷入僵局,服务器停止工作。为了进行调查,我测试了一些具有不同的Spring事务传播的东西,如果我没有记错的话,如果根本没有现有的事务,那么REQUIRES_NEW传播将启动两个连接。这样对吗??我尝试使用Google谷歌搜索,但未找到有关此信息。

我做了一个测试。这是一个示例类:

package test;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class TheService {

@Transactional(propagation=Propagation.REQUIRES_NEW)
public void doSomething() {
System.out.println("Here I am doing something.");
}
}

这是我进行的单元测试:
package test;

import javax.annotation.Resource;

import org.junit.Test;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests;

@ContextConfiguration(locations = {"classpath:test.xml"})
public class TheServiceTest extends AbstractTransactionalJUnit4SpringContextTests {

@Resource
private TheService theService;

@Test
public void test() {
theService.doSomething();
}

}

最后但并非最不重要的是,这是我的测试xml:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.1.xsd"
default-autowire="byName">

<context:component-scan base-package="test" />

<tx:annotation-driven transaction-manager="transactionManager" />

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="operator.entityManagerFactory" />
</bean>

<bean id="operator.entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="operatorPersistenceUnit" />
<property name="dataSource" ref="operator.dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="false" />
<property name="generateDdl" value="true" />
<property name="databasePlatform" value="org.hibernate.dialect.H2Dialect" />
</bean>
</property>
</bean>

<bean id="operator.dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="org.h2.Driver" />
<property name="url" value="jdbc:h2:mem:operator" />
<property name="username" value="sa" />
<property name="password" value="" />
<property name="maxActive" value="1" /> <!-- NOTE -->
</bean>
</beans>

我想要一个方法REQUIRES_NEW的原因是,至关重要的是不要从中获取任何脏读,并且可以在另一个事务内和外部都可以执行它。

如果我将maxActive属性保持为1,则此测试将死锁并且从不打印任何内容。如果我将其更改为2,则测试将通过。

之所以担心这个问题,是因为即使我将maxActive设置为一个更高的值,并且有足够的线程等待执行此方法,它们最终都可能各自占用一个连接并等待第二个连接。

我做错什么了吗?我有误会吗?

感谢您的帮助!谢谢!

最佳答案

它与propagation=REQUIRES_NEW无关,后者默认情况下不会打开2个连接。问题是您正在扩展AbstractTransactionalJUnit4SpringContextTests

随着测试用例的扩展 AbstractTransactionalJUnit4SpringContextTests ,如您所见,它是@Transactional。该事务(用于测试)由 TransactionalTestExecutionListener 管理。

因此,发生的事情是当您开始测试时,在执行测试方法之前,由测试框架启动事务。接下来,您将调用服务,由于使用@Transactional(propagation=REQUIRES_NEW)进行了注释,因此该服务将启动另一个事务。

该修复非常容易,无需扩展AbstractTransactionalJUnit4SpringContextTests,而只需使用@RunWith(SpringRunner.class)注释您的类。

@RunWith(SpringRunner.class)
@ContextConfiguration(locations = {"classpath:test.xml"})
public class TheServiceTest { ... }

关于java - @Transactional(propagation = Propagation.REQUIRES_NEW)打开两个交易?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44584608/

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