我应该如何最好地锁定和刷新JPA实体?

问题描述:

我对JPA比较陌生,对如何最好地乐观锁定和刷新实体感到非常困惑。我想在我的项目中使用一套通用的方法来处理这个问题。我应该如何最好地锁定和刷新JPA实体?

我可能在不知道实体状态的方法中调用锁定/刷新方法,它可能已经传递了一个detatched或new/not saved实体对象以及先前从数据库读取的实体对象。为了简单起见,我希望我的效用方法能够处理所有可能性。语义我想实现的方法是:

myEntity所refreshAndLock(myEntity所E)
再从数据库读取实体和乐观锁定它,或者什么都不做的实体尚未保存到数据库中。分离的实体也将被重新读取并锁定,并返回管理版本。

MyEntity refresh(MyEntity e)
只需重新读取实体,或者对于尚未保存到数据库的实体执行任何操作。分离的实体也将被重新阅读。

myEntity所lockAndNotRefresh(myEntity所E)
锁定在内存中的实体版本(可能已经过时)

任何提示或链接欣然接受。我还没有设法找到明确的指导,我很惊讶,因为这似乎是一个普遍的要求。

1,我的主要建议是:不要试图实现你自己的通用数据访问层。你有EntityManager在你手中为你做所有的东西。保持你的代码简单,不要过度使用。对于通用层,您很可能会引入新问题并降低可维护性。

第二,你必须问自己,为了决定锁定,你的应用程序的典型用例是什么。锁定总是会带来瓶颈问题和可能的死锁问题。因此,如果您的应用程序读取的内容比写入内容多得多,或者可能不会同时访问同一个实体,那么最好使用乐观锁定,然后处理异常。 JPA为您提供版本控制,因此您始终知道其他某个线程是否改变了您的对象。如果您确实需要悲观锁定,那么请继续为这些情况进行设置。

+0

感谢您的建议。我假设使用JPA版本控制进行乐观锁定。我不清楚什么样的EntityManager接口调用组合可以在未知状态的实体上达到所需的结果。在我看来,在许多情况下,您需要知道实体被锁定的状态(新的,持续的,分离的),这会降低代码的可重用性。我对上述方法的想法是集中与这些模式相关的代码,而不是通过代码库重复它。但是,当然,如你所建议的那样,有优点和缺点。 – Jonathan 2013-04-10 21:36:09

+0

基本上你只有两种可能性:实体或者由EntityManager管理或者不管理。在第一种情况下,您对该实体所做的所有更改都将在事务结束时自动与底层数据库同步。在第二种情况下,如果您从其他位置获取该实体或通过新创建该实体,则可以使用merge()使其进行管理。那么,你为什么觉得,你必须关心实体的状态? EntityManager为你做。在乐观锁定的情况下(是的,通过@Version),你必须关心可能的OptimisticLockExceptions。 – 2013-04-11 05:48:35

+0

关于你不得不重复代码的担心 - 正如我上面所说的,实际上没有关心实体的代码,你所要做的就是让EntityManager知道它。那么你当然可以将一些常见的用例分解为在业务逻辑中不多次使用它们。你可能会关心一个中心点的例外情况。但是,在大多数情况下,你不能也不应该把所有的实体都视为同一个实体,它可能会因用例和用例的不同而异。 – 2013-04-11 05:52:21