如何创建一个线程安全的EntityManagerFactory?

时间:2010-09-14 17:37:30

标签: java multithreading orm jpa

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

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

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

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

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

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

请指出正确的资源。

5 个答案:

答案 0 :(得分:11)

“解决”这个问题的一种简单方法是使用辅助类(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);
        }
    }

   ...

}

而“问题”已经消失。

答案 1 :(得分:3)

我没有看到静态块方法有任何问题。或者您可以通过以下方式执行相同操作,即具有双锁检查的Singleton模式

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;
 }

你会打电话给

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

答案 2 :(得分:1)

创建emf时,需要在对象上放置锁。您可以将锁定放在emf对象本身上,但这不是最佳做法。创建另一个对象:

private object factoryLockObject = new object();

并在创建工厂时将锁定放在上面

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

那有帮助吗?

答案 3 :(得分:1)

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

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

您显示的代码应位于synchronized块内,或者它不是线程安全的。

答案 4 :(得分:0)

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

单例模式答案最适合避免额外调用以有效地检索一个工厂句柄,但请注意,不需要像之前所述的双重检查锁。