【问题标题】:EntityManagerFactory singleton on multi thread多线程上的 EntityManagerFactory 单例
【发布时间】:2019-07-08 18:28:20
【问题描述】:

我有一个像这样工作的应用程序(javaee / wildfly / Maven): 线程processA(在后台触发线程processB)

我正在使用带有@PersistenceContext 的无状态 EJB,在 processA 中一切正常,我的问题是在 processB 上,在 processA 中持久化的实体在 processB 中不是最新的,我认为这是因为 @PersistenceContext 每个都有缓存过程对吗? 所以首先我想找到一种方法来“刷新”缓存,当我在 processB 中使用的唯一方法被调用时,但我没有找到任何可以做的事情......

然后在阅读更多内容后,我发现 EntityManager 不是线程安全的,最好将 @singleton 与仅创建一次的 EntityManagerFactory 一起使用,因为它像这里一样昂贵: https://subhadipsblog.wordpress.com/2017/09/16/correct-way-of-using-entitymanager-in-singleton-ejb/

@Singleton
public class PersistenceService
{
 @PersistenceUnit(name="somePU")
 EntityManagerFactory emf;

如下创建EntityManager:

public void persistenceMethod(Entity myEntity)
{
 EntityManager em = emf.createEntityManager();
 ... //Persistence operations
 em.close();
}

编辑: 所以我添加了这个:

@Singleton
public class PersistenceService {

    @PersistenceUnit(name="MyPu")
    EntityManagerFactory emf;

    public ImportState createEntity(MyEntity myEntity) {

        EntityManager em = emf.createEntityManager();
        em.merge(myEntity);
        em.close();
        }

    public List<MyEntity> getMyEntities() {

        EntityManager em = emf.createEntityManager();
        List<MyEntity> myEntities = em.createQuery("from MyEntity as myEntity, MyEntity.class)
                .getResultList();
        em.close();
        return myEntities;
    }
}

在我的服务中:

@EJB PersistenceService persistenceService;

但我仍然有同样的问题......

  • ThreadA -> persistenceService.createEntity(myEntity) -> 在数据库中创建实体 (org.hibernate.jpa.internal.EntityManagerFactoryImpl@3097af5)
  • ThreadB -> persistenceService.getMyEntities() -> 看不到由 ThreadA 创建的实体 (org.hibernate.jpa.internal.EntityManagerFactoryImpl@3097af5)

编辑线程 B 创建:

ExecutorService executor = Executors.newSingleThreadExecutor();
executor.submit(new Runnable() {
            @Override
            public void run() {
                System.out.println("debut tache " + Thread.currentThread().getName());
                try {
                    System.err.println(persistenceService.getMyEntities());
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                System.out.println("fin tache");
            }
        });

【问题讨论】:

  • ThreadB 将从数据库中获取数据。您是否曾经提交过在 ThreadA 中插入 myEntity 的事务?
  • 当我使用无状态 EJB 和 @PersistenceContext 提交是自动的,所以不,我不提交事务,即使我添加了 em.getTransaction().commit();在关闭 em 之前我有“A JTA EntityManager cannot use getTransaction”错误并且 em.flush() 没有改变任何东西/实体(线程 A)是在我检查过的数据库中创建的
  • 你是如何创建“线程进程B”的?您使用的是哪个版本的 WildFly?
  • Wildfly 10,我已经添加了关于创建线程进程B的代码

标签: multithreading maven jakarta-ee wildfly


【解决方案1】:

这可能是因为您的线程没有正确设置上下文。您需要复制上下文,这可能相当麻烦。如果你想创建线程,你应该使用Java EE Concurrency 实用程序。

【讨论】:

    猜你喜欢
    • 2013-06-02
    • 2012-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多