JPA中是否可以选择在不锁定数据库的情况下加载实体(或列表)?我希望能够通过几种方法做到这一点。JPA是否有可能在不锁定数据库的情况下加载实体,但是当该实体发生任何更改时,只是锁定了数据库中的行?当然,如果在数据库中已更改实体,则验证状态将引发无效状态的异常。
JPA中是否可以选择在不锁定数据库的情况下加载实体(或列表)?
实体可以通过不同的EntityManager调用来加载:
EntityManager.find
EntityManager.createQuery
EntityManager.createNamedQuery
EntityManager.createNativeQuery
您无需LockModeType.None
在这些调用中显式使用。这是JPA中以表示的默认选项LockModeType.None
。
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
调用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
),并且还必须强制对实体的版本列进行更新(递增)。强制版本更新可以立即执行,也可以推迟到刷新或提交之前执行。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句