使用 JPA,我们可以使用手动OPTIMISTIC
或PESSIMISTIC
锁定来处理事务中的实体更改。
如果我们不指定这两种模式之一,我想知道 JPA 如何处理锁定?没有使用锁定模式?
如果我们不定义显式锁定模式,数据库完整性会丢失吗?
谢谢
使用 JPA,我们可以使用手动OPTIMISTIC
或PESSIMISTIC
锁定来处理事务中的实体更改。
如果我们不指定这两种模式之一,我想知道 JPA 如何处理锁定?没有使用锁定模式?
如果我们不定义显式锁定模式,数据库完整性会丢失吗?
谢谢
我浏览了Java Persistence API 2.0 Final Release规范的第 3.4.4 节锁定模式,虽然我找不到任何具体的东西(它没有说明这是默认设置或类似的东西),但有一个脚注说如下。
锁定模式类型 NONE 可以指定为锁定模式参数的值,并且还为注释提供默认值。
该部分是关于LockModeType
可用值的种类及其用法,并描述了哪些方法采用这种类型的参数和诸如此类的参数。
所以,正如它所说LockModeType.NONE
的是注释的默认值(JPA,注释左右)我猜当你使用EntityManager.find(Class, Object)
默认值时LockModeType
。
还有一些其他微妙的提示可以加强这一点。第 3.1.1 节EntityManager 接口。
find 方法(假设它在没有锁的情况下调用或使用 LockModeType.NONE 调用)和 getReference 方法不需要在事务上下文中调用。
这说得通。例如,如果您使用 MySQL 作为数据库并且您选择的数据库引擎是 InnoDB,那么(默认情况下)您的表将使用REPEATABLE READ
,如果您使用其他一些 RDBMS 或其他数据库引擎,这可能会改变。
现在我不确定隔离级别与 JPA 锁定模式有什么关系(尽管看起来是这样),但我的观点是不同的数据库系统不同,所以 JPA 无法为你做出决定(至少根据规范)默认使用什么锁定模式,所以LockModeType.NONE
如果你不指示它会使用它。
我还找到了一篇关于隔离级别和锁定模式的文章,您可能想阅读它。
哦,回答你的最后一个问题。
如果我们不定义显式锁定模式,数据库完整性会丢失吗?
这取决于,但如果您有并发事务,那么答案可能是肯定的。
由于 JPA 2.1 FR
3.2 版本属性
持久性提供程序使用 Version 字段或属性来执行乐观锁定。它由持久性提供者在对实体实例执行生命周期操作的过程中访问和/或设置。如果实体具有使用版本映射映射的属性或字段,则会自动启用乐观锁定。
因此,如果实体是版本化对象,例如已指定 @Version,则默认持久性提供程序将执行乐观锁定。
在规范 persistence_2.0,第 89 页:
如果版本化对象以其他方式更新或删除,则实现必须确保满足 LockModeType.OPTIMISTIC_FORCE_INCREMENT 的要求,即使没有对 EntityManager.lock 进行显式调用。