我尝试为@Transactional
创建测试用例。
@ContextConfiguration(locations = {"classpath:/META-INF/spring/app-context.xml" })
@RunWith(SpringJUnit4ClassRunner.class)
public class TransactionalAnnotationTest {
public static final BigDecimal PROD_ID = new BigDecimal(1234);
@PersistenceContext
HibernateEntityManager em;
@Test
public final void testTransactionIsolation() {
String original = em.find(ProductImpl.class, PROD_ID).getDescription();
// original = "Foo"
updateTx(original);
}
@Transactional
public final void updateTx(String original) {
ProductImpl product = em.find(ProductImpl.class, PROD_ID);
product.setDescription("Bar");
whatIsInDB(original);
}
private void whatIsInDB(String original) {
String sameTxDescription = em.find(ProductImpl.class, PROD_ID).getDescription();
assert !sameTxDescription.equals(original);
}
}
失败了!第二个em.find
是否应该返回带有“Bar”的产品?
答案 0 :(得分:0)
在设置“description”字段
后尝试显式刷新上下文
product.setDescription("Bar");
em.flush();
whatIsInDB(original);
product.setDescription("Bar");
em.flush();
whatIsInDB(original);
答案 1 :(得分:-1)
em.flush()
(感谢@TaoufikMohdit的想法)。如果没有交易,flush()
会抛出TransactionRequiredException
! @Transactional
仅适用于Spring-Managed-Beans。所以我创建了一个服务:
@Service
public class BasicTransactionalService {
@PersistenceContext
HibernateEntityManager em;
@Transactional
public void testFlushInTransactional() {
em.flush();
}
@Deprecated
public void testFlushOutsideTransactional() {
em.flush();
}
@Transactional
public void testFlushSubroutineTransactional() {
testFlushOutsideTransactional();
}
}
我将测试更改为:
@Autowired
BasicTransactionalService bean;
@Test
public void testTransactionIsolation() {
bean.testFlushInTransactional();
}
@Test(expected = TransactionRequiredException.class)
@SuppressWarnings("deprecation")
public void testThrowsTransactionRequiredException() {
bean.testFlushOutsideTransactional();
}
@Test
public void testTransactionalSubroutine(){
bean.testFlushSubroutineTransactional();
}
现在工作正常。
BTW这是我的app-config.xml
<beans>
<bean class="BasicTransactionalService" />
<bean class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean" />
<bean class="org.springframework.orm.jpa.JpaTransactionManager" />
<tx:annotation-driven />
<beans>