我們有一個生產事件導致一堆線程死鎖並且服務器停止工作。爲了嘗試和調查,我測試了一些具有不同春季交易傳播的東西,如果我沒有弄錯,那麼REQUIRES_NEW傳播將在沒有現有交易的情況下啓動兩個連接。它是否正確??我嘗試了谷歌搜索,但沒有找到關於此的信息。@Transactional(propagation = Propagation.REQUIRES_NEW)打開兩個事務?
我做了一個測試。下面是一個示例類:
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設置爲更高的值,並且有足夠的線程等待執行此方法,它們最終都會佔用一個連接並等待第二個連接。
我做錯了什麼?我誤解了任何東西嗎?
我感謝任何幫助!謝謝!
不,它沒有打開2個連接。它在你的測試中有效,因爲1是你的測試打開的(它是事務性的)並且在你的服務中有一個新的,因爲'REQUIRES_NEW' .. –
爲什麼我的測試打開了一個?有沒有辦法避免這種情況?另外,有時爲了查看某個方法是否在事務中,我添加了一個「新的Exception()。printStackTrace()',並且查找了TransactionInterceptor。這個,我在添加測試方法時看不到。 – user3306066
你認爲'AbstractTransactionalJUnit4SpringContextTests'確實......那個'Transactional'部分的類名是有原因的。有更多的方式來處理交易。對於通過手動啓動/停止事務的'TransactionalTestExecutionListener'完成的測試。如果你不想讓你的測試成爲事務性的,不要擴展'AbstractTransactionalJUnit4SpringContextTests'。 –