我试图了解使用SpringJTA进行事务传播的行为 - JPA - Hibernate。
基本上我正在尝试更新实体。为此,我编写了一个测试方法,我使用实体管理器(em)查找方法获取对象(所以现在这个对象是manged对象)。更新获取的对象的属性。然后可选择调用服务层(服务层传播=必需),调用em.merge
现在我有三种变体:
测试方法没有事务性注释。更新属性 获取对象并且不调用服务层。
1.1。结果级别1缓存不会更新,也不会更新到DB。
测试方法没有事务性注释。更新获取的对象的属性。调用服务层。
2.1。结果级别1缓存和数据库更新。
测试方法具有跨国注释,可以是以下任何一种。请参阅下表,了解测试方法的传播值和服务电话的结果。
(服务层传播=必需)
因此,要阅读上表,第1行表示如果Test方法具有事务传播= REQUIRED且是否进行了服务层调用,则结果将更新为1级缓存而不是DB
以下是我的测试用例
@Test
public void testUpdateCategory() {
//Get the object via entity manager
Category rootAChild1 = categoryService.find(TestCaseConstants.CategoryConstant.rootAChild1PK);
assertNotNull(rootAChild1);
rootAChild1.setName(TestCaseConstants.CategoryConstant.rootAChild1 + "_updated");
// OPTIONALLY call update
categoryService.update(rootAChild1);
//Get the object via entity manager. I believe this time object is fetched from L1 cache. As DB doesn't get updated but test case passes
Category rootAChild1Updated = categoryService.find(TestCaseConstants.CategoryConstant.rootAChild1PK);
assertNotNull(rootAChild1Updated);
assertEquals(TestCaseConstants.CategoryConstant.rootAChild1 + "_updated", rootAChild1Updated.getName());
List<Category> categories = rootAChild1Updated.getCategories();
assertNotNull(categories);
assertEquals(TestCaseConstants.CategoryConstant.rootAChild1_Child1,categories.get(0).getName());
}
服务层
@Service
public class CategoryServiceImpl implements CategoryService {
@Transactional
@Override
public void update(Category category) {
categoryDao.update(category);
}
}
DAO
@Repository
public class CategoryDaoImpl {
@Override
public void update(Category category) {
em.merge(category);
}
}
问题 有人可以解释为什么REQUIRED,REQUIRES_NEW和NESTED不会导致插入数据库?
为什么在测试用例中缺少事务注释会导致在我的三个变体中插入数据库?
由于
答案 0 :(得分:1)
您在REQUIRED
,NESTED
和REQUIRES_NEW
看到的效果是由于您正在检查更新过早 < / p>
(我假设您在测试方法到达断言的同一时刻检查db更改,或者在执行测试后以某种方式回滚测试方法事务)
简单地说,您的断言仍然在测试方法中@Transactional
注释创建的上下文中。因此,尚未调用对db的隐式刷新。
在其他三种情况下,测试方法上的@Transactional
注释会不启动要加入的服务方法的事务。因此,事务仅跨越服务方法的执行,并且在>>测试断言之前发生。