JPA和默认锁定模式

使用JPA,我们可以使用手动OPTIMISTICPESSIMISTIC锁定来处理事务中的实体更改。

我想知道如果我们没有指定这两种模式中的一种,JPA如何处理锁定? 没有使用锁定模式?

如果我们没有定义显式锁定模式,数据库完整性是否会丢失?

谢谢

我已经通过章节3.4.4 Java Persistence API 2.0最终版本规范的锁定模式进行了扫描,虽然我找不到任何特定的东西(它没有说明是默认的或类似的东西)但是有一个脚注说如下。

锁定模式类型NONE可以指定为锁定模式参数的值,并且还提供注释的默认值。

该部分是关于可用的LockModeType值的种类及其用法,并描述哪些方法采用此类参数和诸如此类的东西。

所以,因为它说LockModeType.NONE是注释的默认值(JPA,注释左右),我LockModeType你使用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进行显式调用也是如此。