我正在开发一个需要进行一些数据库操作的应用程序。
我为EntityManagerFactory创建了一个静态变量,并在应用程序调用的方法中对其进行了初始化
if (emf == null){
emf = Persistence.createEntityManagerFactory("example");
}
try {
em = emf.createEntityManager();
} catch (Exception ex) {
logger.error(ex.getMessage());
}
这个线程安全吗?如果我在同步块中创建EntityManagerFactory,则等待线程数会增加并使应用程序崩溃。
我查看了文档,看看Persistence.createEntityManagerFactory是否是线程安全的,没有任何成功。
请指出正确的资源。
答案 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()基于类文档,源代码和实际应用程序结果是线程安全的。
单例模式答案最适合避免额外调用以有效地检索一个工厂句柄,但请注意,不需要像之前所述的双重检查锁。