JPA EntityManager 静态还是实例?

发布于 2024-12-23 02:30:03 字数 669 浏览 2 评论 0原文

我过去构建了一些 JPA 东西,每个 DAO 实例使用一个 javax.persistence.EntityManager 实例;这是大多数示例的设置方式。

public class BaseDaoThatEveryDaoExtends {
   @PersistenceContext
   private EntityManager entityManager;
}

我刚刚偶然发现了使用由 PersistenceContext 注释注入的 static javax.peristence.EntityManger 的代码,架构师告诉我这不会导致任何问题即使在具有 JTA 和 XA 数据源的集群应用程序中,他们也从未遇到过任何问题:

public class BaseDaoThatEveryDaoExtends {
   @PersistenceContext
   private static EntityManager entityManager;
}

据我所知,这是一种反模式,因为 EntityManager 保存一些状态信息并将其设为静态进行整个州的申请 宽的。这也使得这些类很难测试。

这样做还有其他缺点吗?或者这是使用 EntityManager 的标准方法吗?

I've built some JPA stuff in the past that used an instance of the javax.persistence.EntityManager per instance of DAO; this is the way most examples are setup.

public class BaseDaoThatEveryDaoExtends {
   @PersistenceContext
   private EntityManager entityManager;
}

I've just stumbled upon code that uses a static javax.peristence.EntityManger injected by a PersistenceContext annotation, the architect tells me this causes no problems and they never had any problem even in a clustered application with JTA and an XA data source:

public class BaseDaoThatEveryDaoExtends {
   @PersistenceContext
   private static EntityManager entityManager;
}

As far as I can tell this is an anti-pattern as the EntityManager holds some state information and making it static makes that whole state application wide. Also this makes the classes very hard to test.

Are there other drawbacks to doing this or is this a standard way of using an EntityManager ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

眼泪都笑了 2024-12-30 02:30:03

我认为主要风险不在于 EntityManager 本身,而在于使用实体管理器时附加到的应用程序上下文。

假设您有两个不同的客户端向服务器发出请求,两者都调用应用程序的两种不同方法,两者都在不同的线程上运行,但都使用相同的实体管理器。

据我所知,实体管理器将附加一个上下文,该上下文将由两个客户端共享。每次将实例加载到上下文时,都可以通过共享实体管理器供线程使用。如果他们篡改彼此的数据会发生什么?如果他们使用不同的事务隔离配置会发生什么?您如何确定客户端 1 不会更改客户端 2 当前使用的数据?

如果其中一个客户端使上下文无效怎么办,另一个客户端会怎么做?您如何以这种方式处理并发?

I think the major risk is not in the EntityManager itself, but in the application context that is attached to the entity manager when it is used.

Let's assume you have two different clients making a request to your server, both invoking two different methods of your application, both running on different threads, but both using the same entity manager.

As far as I know the entity manager will have a single context attached to it, this context will be shared by both clients. Every time you load an instance to the context, will be available to threads through the shared entity manager. What will happen if they tamper with each other's data? What will happen if they are using different transaction isolation configuration?. How can you possibly be sure that client 1 is not altering data being currently used by client 2?

What if one of the clients invalidates the context, what will the other do? How do you deal with concurrency this way?

骄兵必败 2024-12-30 02:30:03

EntityManager 使用线程本地保存其数据,因此可以保存对其的静态引用,因为访问它的所有线程都将被独立处理。事实上,如果 EJB 上下文使用单例模式以静态方式保留 EntityManager,我不会感到惊讶。

就我个人而言,我永远不会以静态的方式定义它。这似乎没有必要,最坏的情况下可能会产生一些不可预见的副作用。

我看到的一个问题是能够无意中从静态方法访问实体管理器:

public class BaseDaoThatEveryDaoExtends {
   @PersistenceContext
   private static EntityManager entityManager;

   public static void doSomeStaticWork(){
      ...
      entityManager.doSomething; //NPE possible!
   }
}

我可以看到实体管理器没有被注入,并在这种情况下导致 NPE。

除此之外,使用 EntityManager 进行测试/模拟可能会存在一些问题。

EntityManager holds onto its data using a threadlocal, so it may be ok to hold a static reference to it since all the threads accessing it would be handled independently. In fact, I would not be surprised if the EJB context holds onto the EntityManager in a static way, using a singleton pattern.

Personally, I would never define it in a static way. It seems unnecessary, and at worst may have some unforeseen side effects.

One problem I can see is the ability to inadvertently accessing the entityManager from a static method:

public class BaseDaoThatEveryDaoExtends {
   @PersistenceContext
   private static EntityManager entityManager;

   public static void doSomeStaticWork(){
      ...
      entityManager.doSomething; //NPE possible!
   }
}

I could see the EntityManager not being injected and resulting in a NPE in this case.

Other than that there may be some issues around testing/mocking using the EntityManager.

吹梦到西洲 2024-12-30 02:30:03

EntityManagerFactory 保证是线程安全的,所以我认为这是“正确”的方式:
在线程不安全的地方使用 EMF 并保护 EntityManger 本身免受线程问题的影响。

The EntityManagerFactory is guaranteed to be thread-safe, so I think this is the "correct" way:
Use the EMF in the thread-un-safe places and protect the EntityManger itself from threading issues.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文