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
How to create a thread safe EntityManagerFactory?
提问by Vanchinathan Chandrasekaran
I'm working on an application that needs to do some database operations.
我正在开发一个需要执行一些数据库操作的应用程序。
I created a static variable for EntityManagerFactory
and 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 EntityManagerFactory
in 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.createEntityManagerFactory
is 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 EntityManagerFactory
in 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 emf
object 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 synchronized
block, 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.
单例模式答案对于避免额外调用以有效检索一个工厂句柄是最正确的,但请注意,如前所述,不需要双重检查锁。