当前位置: 首页 > 知识库问答 >
问题:

事务传播如何影响数据库中的更新

尚恩
2023-03-14

我正在尝试使用SpringJTA-JPA-Hibernate了解事务传播的行为。

本质上,我正在尝试更新一个实体。为此,我编写了一个测试方法,其中我使用实体管理器(em)查找方法获取对象(所以现在这个对象是管理对象)。更新获取的对象的属性。然后可选地调用正在调用em.merge的服务层(服务层传播=必需)

现在我这里有三个变体:

> < li>

测试方法没有事务注释。更新提取的对象的属性,不调用服务层。

1.1. 结果级别 1 缓存不会更新,数据库也不会更新。

测试方法没有事务注释。更新提取对象的属性。调用服务层。

2.1.结果级别1缓存和数据库得到更新。

测试方法具有跨国注释,可以是以下任何一种。请参阅下表,了解测试方法的传播值和服务调用的结果。

(服务层传播=必需)

因此,要阅读上表,第1行表示如果Test方法具有事务传播=REQUIRED并且如果进行了服务层调用,则结果是更新到Level 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);
        }
    }

 @Repository
    public class CategoryDaoImpl {
    @Override
        public void update(Category category) {
            em.merge(category);
        }
    }

问题:有人能解释为什么REQUIRED、REQUIRES_NEW和NESTED不会导致在DB中插入吗?

为什么在我的三个变体中,测试用例上缺少事务注释会导致数据库中的插入?

谢谢

共有1个答案

袁凌
2023-03-14

您看到的<code>REQUIRED</code>、<code>NESTED</code>和<code>requireds_NEW</code>的效果是由于您检查更新太早

(我在这里假设您在测试方法到达断言的同时检查db更改,或者您在执行测试后以某种方式回滚测试方法事务)

很简单,您的断言仍然在测试方法中的@Transactional注释创建的上下文中。因此,尚未调用数据库的隐式刷新。

在其他三种情况下,测试方法上的@Transactional注释不会启动服务方法加入的事务。因此,事务仅跨越服务方法的执行,并且刷新在测试断言之前发生。

 类似资料:
  • 我试图理解Spring事务概念。如下所示,我必须将数据插入两个不同的数据库(iSeries和DB2),但我们的iSeries版本不支持两阶段提交。要求是,只有当两个插入都成功时才应该提交事务,否则应该回滚。 如果我根据需要使用传播或REQUIRES\u NEW,我会得到错误“非法尝试使用现有的两阶段资源提交一阶段资源”。 但是如果我使用NOT_SUPPORTED或支持,它工作正常(即如果其中一个插

  • 我有3列(时间,值,结果)的度量表。时间和值是时间序列数据库需要的基础。结果列标记可以具有以下值之一(成功/硬失败/软失败/未知)。 我想在给定的时间窗口内跟踪成功率(成功/总成功率)(因为我将在grafana上使用它,时间窗口可能会改变,并且应该支持动态时间范围查询) 我在流入量0.9上尝试过的东西: Grafana有一个百分比堆栈选项来显示计数值。不幸的是,它不显示百分比值。它只是显示了分布的

  • 在下面的文章中说, 在此处输入链接描述 需要传播–支持当前交易;如果不存在,请创建一个新的。 下面是一个产品代码,然后是两个表的产品详细信息。 我的问题是什么时候会发生这种行为?我的意思是,当前交易怎么会结束?是在保存还是更新之后? 如果我们使用PROPAGATION_REQUIRED假设当前事务在插入产品后结束。然后一个新的事务来了,但是如果插入产品数量时出现任何故障,它只会回滚数量而不是输入的

  • 我想使用spring测试框架测试hibernate Session的save()方法。@测试方法为: 我想刷新用户到数据库。我希望我的用户在此方法后在数据库中 然后我要使用spring data framework转到database并通过下一行获取这个保存的用户: 非常感谢您的回应。问题是方法flush()没有将我的用户放入数据库,我尝试了isolation.read_uncommitted,但

  • 一、Attach数据库: ATTACH DATABASE语句添加另外一个数据库文件到当前的连接中,如果文件名为":memory:",我们可以将其视为内存数据库,内存数据库无法持久化到磁盘文件上。如果操作Attached数据库中的表,则需要在表名前加数据库名,如dbname.table_name。最后需要说明的是,如果一个事务包含多个Attached数据库操作,那么该事务仍然是原子的。见如下示例:

  • 本文向大家介绍物联网如何影响大数据,包括了物联网如何影响大数据的使用技巧和注意事项,需要的朋友参考一下 当涉及到当今最受关注的两种技术时,大数据和物联网(IoT)可能正处于主导地位。在过去的几年中,大数据在许多领域都取得了进步。尽管物联网恰好与众不同,但它已与大数据紧密相连。 什么是大数据? 大数据本质上是大量复杂形式的数据。具体来说,它还涉及使用预测分析和方法,这些方法和方法可从此类数据中提取有