EntityManagerFactory单例在多线程上

时间:2019-07-08 18:28:20

标签: multithreading maven java-ee wildfly

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

我将无状态EJB与@PersistenceContext一起使用,在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)

编辑threadB创建:

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

1 个答案:

答案 0 :(得分:0)

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