JPA toplink 中是否可以实现列级乐观锁定?

发布于 2024-10-09 16:06:10 字数 627 浏览 0 评论 0原文

我研究了 JPA 中的乐观锁定,在数据库中添加 @Version 注释以及版本列以及它如何由 EntityManager 等管理。

文档说< strong>(用我自己的话说)乐观锁在对象级别是有效的。我可以说确实如此,因为版本定义位于实体类中。

这意味着:

  1. userA select row_A (只是数据库表中的一行)

  2. userB select row_A

  3. userA update用户名列的 row_A(此处版本更改)

  4. userB 更新用户名列的 row_A(抛出 optimisticLockException)

到目前为止,一切都很好。

但是想想在步骤4,如果

userB更新phoneNumber的row_A

我知道仍然会抛出optimisticLockException,但是有什么方法可以按列级别而不是对象级别进行锁定吗?

对我来说,拥有列级锁定会很好,但我也不确定有什么缺点即使有可能,这也会带来。

I studied about optimistic locking in JPA, adding @Version annotation with version column in DB and how it is managed by EntityManager etc

The doc says (in my own word) optimistic lock is effective in object-level. I can tell it is indeed so because the version definition sits in entity class.

This means:

  1. userA select row_A (just a row in db table)

  2. userB select row_A

  3. userA update row_A of username column (version changes here)

  4. userB update row_A of username column (optimisticLockException thrown)

So far so good.

But thinking about at step4, if

userB update row_A of phoneNumber for instance.

I know optimisticLockException is still thrown but is there any way to lock by column level instead of object-level?

For me it would be nice to have column-level lock but I'm also not sure what disadvantage would that bring even though it is possible.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

旧城空念 2024-10-16 16:06:10

不。请记住,JPA 所做的只是将对象映射到底层关系数据库。因此表中的每条记录(行)最终都是对象的实例。

数据库通常锁定记录而不是列。锁定整个列几乎就像表上的独占锁一样。

No. Remember that what JPA is doing is just mapping Objects to the underlying Relational database. So each record (row) in a table ends up being an instance of an object.

Databases normally lock records not columns. Locking a whole column is pretty much nearly like an exclusive lock on a table.

燕归巢 2024-10-16 16:06:10

接受的答案并不完全正确。在普通 JPA 级别确实如此,但是,您可以利用提供程序特定的功能来获取列级别锁。例如,Glassfish 3.0+ 中的默认提供程序 Eclipselink 支持乐观锁扩展,可在该领域提供更大的灵活性。

请参阅 用于乐观锁定的 Eclipselink JPA 扩展

乐观版本锁定策略和级联

了解有关 Eclipselink 乐观字段锁定策略的详细信息。

The accepted answer is not entirely true. It is true at the vanilla JPA level, however, you can take advantage of provider specific functionality to obtain column level locks. For example Eclipselink, the default provider in Glassfish 3.0+, supports Optimistic lock extentions that provide greater flexibility in this area.

See Eclipselink JPA Extensions for Optimistic locking

also

Optimistic Version Locking Policies and Cascading

for details on Optimistic field locking policies for Eclipselink.

终遇你 2024-10-16 16:06:10

我可以看到这种锁定的使用,但它会违反数据库更新的原子性。想象一下我正在编写一个银行应用程序,人们有余额和透支限额。说我开始:

Customer  | Balance | Overdraft Limit
Shirakawa |  -30000 |          -50000

然后白川先生过来,通过不同的收银员同时进行两笔交易;其中一笔提取了 15000 日元,另一笔则将透支限额降低至 40000 日元。这些事务中的每一个本身都完全没问题,并且不会违反业务逻辑中的任何约束。但结果是:

Customer  | Balance | Overdraft Limit
Shirakawa |  -45000 |          -40000

呃哦。

我承认这是一个人为的例子。但这是不支持列级并发更新的一般原因。

不过,您可以做的是将记录中可同时更新的部分分解为单独的实体,并分别更新它们。要将其应用于上面的示例,假设我们有一个帐户表(如上所述),还有一个透支协议表,具有一对一的关系。然后我们就会:

Customer  | Balance
Shirakawa |  -45000

Customer  | Overdraft Limit
Shirakawa |          -40000

我们可以并行更新它们。在这种情况下,这将是一个坏主意,但它可能对您有用。

I can see the use of that sort of locking, but it would violate the atomicity of the database update. Imagine i'm writing a bank application, where people have balances and overdraft limits. Say i start with:

Customer  | Balance | Overdraft Limit
Shirakawa |  -30000 |          -50000

Then Shirakawa-san comes along and makes two transactions at once, via different cashiers; with one, he withdraws 15000 yen, and with the other, he reduces the overdraft limit to 40000 yen. Each of those transactions is perfectly okay on its own, and would not violate any constraints in the business logic. But the result is:

Customer  | Balance | Overdraft Limit
Shirakawa |  -45000 |          -40000

Uh-oh.

I admit this is a contrived example. But this is the general reason why column-level concurrent updates are not supported.

What you could do, though, is to factor out the concurrently updatable parts of the record into separate entities, and update them separately. To apply that to the above example, say we had an account table, as above, and also an overdraft agreement table, with a one-to-one relationship. Then we would have:

Customer  | Balance
Shirakawa |  -45000

Customer  | Overdraft Limit
Shirakawa |          -40000

And we could update those in parallel. In this case, that would be a bad idea, but it could be useful for you.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文