java 如何创建线程安全的 EntityManagerFactory?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3711439/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 03:06:55  来源:igfitidea点击:

How to create a thread safe EntityManagerFactory?

javamultithreadingormjpa

提问by Vanchinathan Chandrasekaran

I'm working on an application that needs to do some database operations.

我正在开发一个需要执行一些数据库操作的应用程序。

I created a static variable for EntityManagerFactoryand initializeded it in the method that gets called by the application

我创建了一个静态变量EntityManagerFactory并在应用程序调用的方法中对其进行了初始化

 if (emf == null) {
      emf = Persistence.createEntityManagerFactory("example");
 }

 try {
      em = emf.createEntityManager();
 } catch (Exception ex) {
      logger.error(ex.getMessage());
 }

Is this thread-safe? If I create the EntityManagerFactoryin a synchronized block, the number of the waiting threads increases and crashes the application.

这是线程安全的吗?如果我EntityManagerFactory在同步块中创建,等待线程的数量会增加并使应用程序崩溃。

I looked at the docs to see whether the Persistence.createEntityManagerFactoryis thread-safe without any success.

我查看了文档以查看它是否Persistence.createEntityManagerFactory是线程安全的,但没有成功。

Please direct me to the right resources.

请指导我找到正确的资源。

回答by Pascal Thivent

An easy way to "solve" this would be to use a helper class (a la HibernateUtil) and to initialize the EntityManagerFactoryin a static initialization block. Something like this:

“解决”这个问题的一种简单方法是使用辅助类(a la HibernateUtil)并EntityManagerFactory在静态初始化块中初始化 。像这样的东西:

public class JpaUtil { 
    private static final EntityManagerFactory emf;

    static {
        try {
            factory = Persistence.createEntityManagerFactory("MyPu");
        } catch (Throwable ex) {
            logger.error("Initial SessionFactory creation failed", ex);
            throw new ExceptionInInitializerError(ex);
        }
    }

   ...

}

And the "problem" is gone.

而“问题”就没有了。

回答by Rajesh John

I am not seeing any issues with the static block approach. Or you can do the same in the below manner which is a Singleton pattern with double-lock check

我没有看到静态块方法有任何问题。或者你可以用下面的方式做同样的事情,这是一个带有双锁检查的单例模式

public class JPAHelper {

 private static JPAHelper myHelper = new JPAHelper();
 private static EntityManagerFactory myFactory = null;

 /**
  * Private constructor. Implementing synchronization with double-lock check
  */
 private JPAHelper() {

  if(myFactory == null) {
   synchronized (JPAHelper.class) {

    // This second check will be true only for the first thread entering the block incase 
    // of thread race
    if(myFactory == null) {
     myFactory = Persistence.createEntityManagerFactory("MyUnit");
    }
   }
  }
 }

 /**
  * Static Accessor Method
  * @return
  */
 public static JPAHelper getInstance() {
  if(myHelper == null) {
   myHelper = new JPAHelper();
  }
  return myHelper;
 }


 public EntityManagerFactory getJPAFactory() {
  return myFactory;
 }

And you will call

你会打电话

EntityManager myManager = JPAhelper.getInstance().getJPAFactory().createEntityManager();

回答by Brad

You need to put locks on an object when you are creating the emf. You canput the locks on the emfobject itself, but that's not best practice. Create another object:

创建emf. 您可以将锁定放在emf对象本身上,但这不是最佳实践。创建另一个对象:

private object factoryLockObject = new object();

and put your locks on it while creating the factory

并在创建工厂时锁定它

lock(factoryLockObject) {
   if (emf == null) {
      emf = Persistence.createEntityManagerFactory("example");
   }
}

Does that help?

这有帮助吗?

回答by erickson

Whether createEntityManagerFactory()is thread-safe or not, you need some strategy so that it is invoked only once. In other words, that question is irrelevant, because you must ensure that only one thread calls it.

无论是否createEntityManagerFactory()是线程安全的,您都需要一些策略使其仅被调用一次。换句话说,这个问题无关紧要,因为您必须确保只有一个线程调用它。

If simply waiting for another thread to create the factory crashes your application, what will happen when every thread creates its own, clobbering the work of other threads in the process?

如果只是等待另一个线程创建工厂会使您的应用程序崩溃,那么当每个线程创建自己的线程并破坏进程中其他线程的工作时会发生什么?

The code you show should be inside a synchronizedblock, or it is not thread safe.

您显示的代码应该在一个synchronized块内,否则它不是线程安全的。

回答by Darrell Teague

The answer to the question is: YES, createEntityManagerFactory() is thread-safe based on the class documentation, source and real-world application results.

问题的答案是:是的,根据类文档、源代码和实际应用程序结果,createEntityManagerFactory() 是线程安全的。

The Singleton Pattern answer is most correct for avoiding an additional call to retrieve the one factory handle efficiently but note there is no need for a double-check lock as commented earlier.

单例模式答案对于避免额外调用以有效检索一个工厂句柄是最正确的,但请注意,如前所述,不需要双重检查锁。