JPA中是否有选项可以在不锁定数据库的情况下加载实体(或列表)? 我希望能够用几种方法来做到这一点。 JPA也可以在不锁定数据库的情况下加载实体,但是当该实体发生任何变化时,它会锁定数据库中的行吗?验证状态当然,如果实体已在数据库中更改,则抛出无效状态的异常。
答案 0 :(得分:1)
JPA中是否有一个选项可以在不锁定数据库的情况下加载实体(或列表)?
可以通过不同的EntityManager调用来加载实体:
EntityManager.find
EntityManager.createQuery
EntityManager.createNamedQuery
EntityManager.createNativeQuery
您无需在这些调用中明确使用LockModeType.None
。这是由LockModeType.None
表示的JPA中的默认选项。
JPA也可以在不锁定数据库的情况下加载实体,但是当该实体发生任何变化时,它会锁定数据库中的行吗?
可以通过不同的电话锁定实体:
EntityManager.find
EntityManager.lock
EntityManager.refresh
Query.setLockMode
我认为JPA是可能的,但不能保证,因为它取决于持久性提供程序(特定于供应商)和使用的锁定类型。
无论如何,这种情况可能如下所示:
// begin tx
...
SomeEntity e = em.find(SomeEntity.class, id);
// change the entity
em.lock(e, LockModeType.OPTIMISTIC); // LockModeType.OPTIMISTIC_FORCE_INCREMENT
...
// commit tx
现在,它依赖于持久性提供程序,锁定是否会(在调用锁定时)或延迟(当tx完成时)。请记住,另一个事务可能会将实体锁定为第一个,并且最终会回滚。
从 JPA规范2.0 ,章节 3.4.4.1 OPTIMISTIC,OPTIMISTIC_FORCE_INCREMENT :
如果交易
T1
在{a}上调用lock(entity, LockModeType.OPTIMISTIC)
版本化对象,实体管理器必须确保两者都没有 可能会出现以下现象:
- P1(脏读):事务
T1
修改一行。然后另一个事务T2
读取该行并获取修改后的值, 在T1
提交或回滚之前。最终交易T2
成功提交;T1
是否提交或滚动无关紧要 返回以及是否在T2
提交之前或之后执行此操作。- P2(不可重复读取):事务
T1
读取一行。然后,另一个事务T2
会在T1
之前修改或删除该行 承诺。这两个事务最终都成功提交。这通常由实体经理获得锁来实现 在底层数据库行上。 虽然乐观并发, 通常不会立即获得长期数据库读锁 允许兼容的实现获得立即锁定 (只要在提交完成之前保留它)。如果是锁 推迟到提交时间,它必须保留到提交 完成。任何支持可重复读取的实现 防止上述现象的方法是允许的
如果事务
T1
调用 版本化lock(entity,LockModeType.OPTIMISTIC_FORCE_INCREMENT)
对象,实体管理者必须避免现象P1和P2(如同LockModeType.OPTIMISTIC
)并且还必须强制更新(增量) 到实体的版本列。 强制版本更新可能是 立即执行,或者可以推迟到刷新或提交。