【发布时间】: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