我在JPA中研究了optimistic locking
,在数据库中添加了@Version annotation
版本列,以及EntityManager
等如何管理
文档说(用我自己的话说)乐观锁在对象级别是有效的。我可以说它确实是这样,因为版本定义位于实体类中。
这意味着:
userA选择row_A(只是db表中的一行)
userB select row_A
userA更新用户名栏的row_A(此处版本更改)
userB更新用户名列的row_A(抛出optimisticLockException)
到目前为止一切顺利。
但是在第4步考虑,如果
例如 userB update row_A of phoneNumber
。
我知道仍然会抛出optimisticLockException,但是否有任何方法可以按列级而不是对象级锁定?
对我来说,拥有列级锁定会很好,但我也不确定即使有可能会带来什么样的劣势。
答案 0 :(得分:2)
没有。请记住,JPA正在做的只是将对象映射到底层的Relational数据库。因此,表中的每个记录(行)最终都是对象的实例。
数据库通常锁定记录而不是列。锁定整列几乎就像桌子上的独占锁。
答案 1 :(得分:2)
接受的答案并非完全正确。但是,在vanilla JPA级别上,您可以利用提供程序特定的功能来获取列级锁定。例如,Glasscl 3.0+中的默认提供程序Eclipselink支持乐观锁定扩展,可在此区域提供更大的灵活性。
请参阅Eclipselink JPA Extensions for Optimistic locking
也
Optimistic Version Locking Policies and Cascading
有关Eclipselink的乐观字段锁定策略的详细信息。
答案 2 :(得分:1)
我可以看到使用那种锁定,但它会违反数据库更新的原子性。想象一下,我正在写一个银行应用程序,人们有平衡和透支限制。我先说:
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
我们可以并行更新。在这种情况下,这将是一个坏主意,但它可能对您有用。