【问题标题】:How should I best lock and refresh JPA entities?我应该如何最好地锁定和刷新 JPA 实体?
【发布时间】:2013-03-27 23:25:29
【问题描述】:

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

我可能从一个不知道实体状态的方法中调用锁定/刷新方法,它可能已经传递了一个分离的或新的/未保存的实体对象,以及一个先前从数据库中读取的对象。为简单起见,我希望我的实用程序方法能够处理所有可能发生的情况。从语义上讲,我尝试实现的方法是:

MyEntity refreshAndLock(MyEntity e)
从数据库中重新读取实体并乐观地锁定它,或者对尚未保存到数据库的实体不做任何事情。分离的实体也将被重新读取和锁定,并返回一个托管版本。

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

MyEntity lockAndNotRefresh(MyEntity e)
锁定内存中实体的版本(可能已经过时)

感谢您接受任何提示或链接。我还没有找到明确的指导,对此我感到很惊讶,因为这似乎是一个常见的要求。

【问题讨论】:

    标签: jpa-2.0 java-ee-6


    【解决方案1】:

    第一,我的主要建议是:不要尝试实现自己的通用数据访问层。您可以使用 EntityManager 为您做所有事情。保持你的代码简单,不要过度设计。使用通用层很可能会引入新问题并降低可维护性。

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

    【讨论】:

    • 感谢您的建议。我假设使用 JPA 版本控制进行乐观锁定。我不清楚 EntityManager 接口调用的哪种组合可以在未知状态的实体上实现所需的结果。在我看来,在许多情况下,您需要知道被锁定实体的状态(新的、持久的、分离的),这会降低代码的可重用性。我对上述方法的想法是集中与这些模式相关的代码,而不是在代码库中重复它。但是,当然,正如您所建议的那样,有利有弊。
    • 基本上你只有两种可能:实体是否由 EntityManager 管理。在第一种情况下,您对实体所做的所有更改都会在事务结束时自动与底层数据库同步。在第二种情况下,您从某个其他点获取该实体或通过 new 创建它,您可以使用 merge() 对其进行管理。那么,为什么你觉得,你必须关心实体的状态? EntityManager 为您完成。在乐观锁定的情况下(是的,通过@Version),您必须关心可能的 OptimisticLockExceptions。
    • 关于你不得不一遍又一遍地重复代码的恐惧——正如我上面所说的,实际上没有代码可以关心实体,你所要做的就是让 EntityManager 知道它。然后,您当然可以排除一些常见的用例,以免在您的业务逻辑中多次使用它们。而且您可能会关注中心点的异常。但同样,在大多数情况下,您不能或不应该对所有实体一视同仁,它可能因用例而异,如何处理它以及例外情况。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-16
    • 1970-01-01
    • 2013-06-27
    相关资源
    最近更新 更多