Spring Data JPA:删除乐观锁定语义

2024-03-09

有一个实体Foo with a @Version柱子。如果我想删除它,我希望 Spring Data JPA 和/或 Hibernate 检查@Version列与数据库中的列匹配。如果不符合,则应拒绝删除。对于独立实体来说,这可以按预期工作:

@Transactional
public void delete(Foo foo) {
    fooRepository.delete(foo); // throws ObjectOptimisticLockingFailureException
}

但是,如果我首先从存储库加载实体,然后使用不同版本在同一事务中删除它,则无论 的值如何,删除都会通过@Version column:

@Transactional
public void delete(int fooId, long version) {
    Foo foo = fooRepository.findOne(fooId);
    foo.setVersion(version);
    fooRepository.delete(foo); // passes regardless of value of version
}

当我查看 Hibernate 调试输出时,会执行版本比较(delete from foo where id=? and version=?)但没有达到我预期的效果。

我缺少什么?


来自JPA规范 http://download.oracle.com/otndocs/jcp/persistence-2_1-fr-eval-spec/index.html, 部分3.4.2:

实体可以访问其版本字段或属性的状态,或者 导出一个方法供应用程序用来访问版本,但是 不得修改版本值。除章节中注明的例外情况外 4.10 中,仅允许持久化提供者设置或更新对象中版本属性的值。

version 属性的目的是防止我们在当前持久化上下文中加载对象后可能发生的并发更新,Hibernate 通过忽略您手动设置的任何值来实现它,而是使用从数据库获取的值对象已加载。为了验证这一点,enable https://stackoverflow.com/a/2536835/4754790还打印绑定变量值,您会注意到使用了数据库中的值。

例如,在使用 DTO 时实际使用的标准解决方案是在从 DTO 更新实体状态时手动执行检查:

if (entity.getVersion() != dto.getVersion()) {
    throw new OptimisticLockException("...");
}

当然,您可以通过从为所有可版本实体提供此检查的基类进行扩展,或在某些 util 方法中进行扩展,使其更加通用。例如,有些作者直接在版本设置器中执行此操作:

public void setVersion(long version) {
    if (this.version != version) {
      throw new OptimisticLockException("...");
    }
} 

Hibernate 自动对分离实体执行此检查,如在实现中所示DefaultMergeEventListener https://github.com/hibernate/hibernate-orm/blob/5.1/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultMergeEventListener.java#L316:

else if (isVersionChanged(entity, source, persister, target)) {
    if (source.getFactory().getStatistics().isStatisticsEnabled()) {
        source.getFactory().getStatisticsImplementor()
            .optimisticFailure(entityName);
    }
    throw new StaleObjectStateException(entityName, id);
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring Data JPA:删除乐观锁定语义 的相关文章

随机推荐

  • 为 Jekyll 服务时参数数量错误(1 对 2)

    全新安装 Jekyll 和 Octopress 启动服务器时 它会产生 Homes MacBook Pro octopress home jekyll serve Configuration file Users home octopres
  • 带有曲面细分着色器的 GL_Triangles

    当我使用曲面细分着色器时 我是否必须从 CPU 程序补丁而不是三角形传递 glDrawArrays GL PATCHES 0 3 Works with Tess Shaders glDrawArrays GL TRIANGLES 0 3 W
  • IOS FacebookShare 返回错误“保留”

    我尝试过搜索但找不到答案 我已经编写了一个应用程序 我正在尝试将内容分享到 Facebook 基本上我想分享一个网址 也许还有一个引言或标题 我不断收到一个名为 保留 的错误 但我不确定它的含义或如何修复它 任何帮助都会很棒 func fb
  • 如何从 android 中的列表视图中获取下一个和上一个列表项

    我有一个列表视图 其中包含一些类似于 Twitter 推文的列表项 当我单击特定列表项时 它会显示该特定列表项的详细信息 在该活动中 包含两个按钮 用于显示 下一个 列表项详细信息和 上一个 列表项详细信息 Problem 如何使用视图翻转
  • Python 数据类:如果 __post_init__ 执行类型转换,则使用什么类型?

    我有一个 Python 类 其中有一个可以传递多种序列类型之一的字段 为了简化 我将坚持使用元组和列表 init 将参数转换为MyList from typing import Union from dataclasses import d
  • iphone <-> 现实世界连接

    有关如何初始化与 iphone 的串行通信的任何指示吗 或者还有其他与外部硬件交互的想法吗 将外部硬件连接到 iPhone 的唯一受支持的方式是通过 iPod 配件协议 通过 30 针连接器 该计划的详细信息位于http developer
  • 我可以制作 pip 可安装包而不在 pypi 中注册包吗?

    我正在尝试按照以下描述使用 python3 制作 pip 可安装包 Url here https marthall github io blog how to package a python app 我使用成功安装了我的包sudo pyt
  • 如何在Python中删除列表中满足特定条件的最左/最右元素? [复制]

    这个问题在这里已经有答案了 我有一个如下所示的列表 a b c 这是解析 脏 csv 文件的结果 我现在想去掉右侧的空列 我不能只使用计数 因为长度是可变的 我也不能只使用简单的过滤 因为还有一些行看起来像这样 a1 c1 所以我必须保留空
  • 为什么 Hibernate 会抛出 org.hibernate.exception.LockAcquisitionException?

    我有这个方法 mymethod long id Person p DAO findPerson id Car car new Car car setPerson p p getCars add car DAO saveOrUpdate ca
  • for循环中的Qt字符串生成器

    下列的this http labs qt nokia com 2011 06 13 string concatenation with qstringbuilder and this http doc snapshot qt project
  • 反斜杠后是否允许有空格来继续一行(在 C/C++ 中)[重复]

    这个问题在这里已经有答案了 使用时 要续行 是否允许有空格after反斜杠 在同一行 换行符应紧接在反斜杠之后 C 标准 N4140 状态 2 2 翻译阶段 反斜杠字符的每个实例 紧随其后的换行符被删除 拼接物理源线以形成逻辑源线 任何物理
  • 将 django 应用程序移动到子文件夹和 url.py 错误

    我有一个关于将 django 应用程序放入 apps 子目录的问题 我在项目根目录中有一个名为 faktura 的应用程序 我不喜欢它放在那里 我想将所有应用程序存储在 apps 子目录下 所以 我发现我可以将python路径扩展到 app
  • MVC 5 ViewBag 安全性

    我正在编写一个 MVC 互联网应用程序 我有一个关于使用 ViewBag 的问题 在我的许多控制器中 我都有 SelectList 对象 用户可以在其中选择一个对象 所选对象是我的模型的外键值 我的问题是 我应该使用 ViewBag 吗 V
  • 使用 htaccess 将 HTTP GET 请求重写为 Apache 中的 POST

    我需要更改第三方 PHP 应用程序的行为 并在此后不久恢复更改 如果我可以重写 GET 请求并从中生成 POST 请求 我将节省大量时间 并且可以避免在应用程序中进行任何更改 是否可以改造GEThttp website action1 pa
  • 如何用C语言打印

    一个 C 初学者 事实上这是我的第一个测试程序 我实际上不知道如何将该数字打印到终端 include
  • 我可以同时使用 setupWithNavController 和 setOnNavigationItemSelectedListener

    我有一个带有 BottomNavigationView 的活动 其中包含 5 个项目和片段来显示页面 我将 NavController 设置如下 NavigationUI setupWithNavController mBottomNavi
  • PHP 获取前一个数组元素并知道当前数组键

    我有一个带有特定键的数组 array 420 gt array 430 gt array 555 gt array 在我的应用程序中 我知道当前的密钥 例如555 我想获取前一个数组元素 在此示例中 它是带有键的数组元素430 我怎样才能在
  • MQTT:如何知道 puback 是针对哪条消息的?

    我正在尝试设置一个 MQTT 服务器 它将客户端发送的消息保存到本地数据库中 每条消息都有一个 成功接收 标志 当接收客户端为收到的每条消息 QOS 1 返回 puback 时 我想翻转该标志 问题是 当我发布消息时 服务器正确接收从接收客
  • Symfony 2 多个应用程序?

    这似乎是与 Symfony2 相关的最可怕的话题 因为经过一周的搜索和测试 我仍然找不到答案 简而言之 我正在构建一个具有多个子域的应用程序 我希望为所有子域提供不同的配置 同时共享来自 src 的多个捆绑包 更重要的是 导入中央配置和路由
  • Spring Data JPA:删除乐观锁定语义

    有一个实体Foo with a Version柱子 如果我想删除它 我希望 Spring Data JPA 和 或 Hibernate 检查 Version列与数据库中的列匹配 如果不符合 则应拒绝删除 对于独立实体来说 这可以按预期工作