【问题标题】:Detached JPA Object Not Getting Version Field Populated分离的 JPA 对象未填充版本字段
【发布时间】:2012-02-23 20:28:33
【问题描述】:

我正在使用连接到 MSSQL 数据库的 Roo 1.2.1、JPA 2 和 Hibernate 3.6。

我有一个接受 JSON 并将其解析为实体的 Web 服务;显然,@Version 列将是 0,因为调用该服务的人对此一无所知。当我第一次调用 merge() 时,它工作正常。该对象已正确持久化,并且版本列设置为 1。但是下次我使用相同的数据调用 Web 服务时,它说该对象已过时,这在技术上是正确的,因为版本始终为 0。

他们传递给我们的 ID 保证是唯一的,所以我们使用它作为我们的主键。

我想这会由实体经理以某种方式处理。

所以我的问题是:如何在不先从数据库加载所有实体、然后更新字段、然后重新持久化它们的情况下处理这个问题?这似乎是一种黑客行为。也许我的做法是错误的?

我的实体如下所示:

@RooJavaBean
@RooToString
@RooJson
@RooJpaActiveRecord(table = "MYTABLE", persistenceUnit = "myPersistenceUnit",
    transactionManager = "myTransactionManager", versionField = "version", identifierColumn = "myIdField")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@Entity
public class MyEntity {
  @Id
  @Column(name = "myIdField")
  private long myIdField;

  @Version
  @Column(name = "version")
  private long version;

  @Column("myColumn")
  private String someValue;
}

【问题讨论】:

    标签: hibernate jpa persistence spring-roo


    【解决方案1】:

    您必须决定是否要乐观锁定。

    如果您想用客户端发送的内容更新数据库,而不管在他获取对象和更新对象之间的潜在并发更新,那么这意味着您不想要乐观锁定,并且应该'不是实体中的版本字段。

    如果你想要乐观锁定,那么版本应该是合并实体的一部分。这就是机制的工作原理:它检查保存的版本号是否与传递的版本号相同。所以如果你总是传递 0,显然,它永远不会起作用。

    最简单的方法当然是让它成为发送给客户端和由客户端发送的 JSON 对象的一部分。您还可以想象将给定实体的版本(发送给客户端以供将来更新,因此密钥将是 clientId-entityId)存储在某个内存或数据库表中,但实现起来会更加困难。

    【讨论】:

    • 不幸的是 Roo 强迫你有一个 @Version 字段,所以我有点坚持。
    • 我不认识 Roo,但我在论坛帖子中看到如果您将 versionField 设置为“”,它将被忽略。
    • 这毫无意义。您需要传递从数据库加载实体时的对象版本。如果您对从客户端收到的内容进行哈希处理,它显然与存储在数据库中的内容不同,除非客户端没有修改任何内容。而且,我不认为String可以用作版本字段。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-04-12
    • 2023-04-01
    • 2019-01-13
    • 2021-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多