Java 来自其他线程的JTA事务(之前的JSR-236)
我的JavaEE应用程序应该有一个后台线程,用于更新DB状态。为此,我想使用JPA。做这件事的最佳实践是什么?我们的EE容器是之前的JSR-236,所以ManagedExecutorService不是我们的选择 顺便说一句,我尝试了下面的代码,但它没有工作-没有抛出异常,但没有保存到DB中。没有后台线程并使用注入的EntityManager保存所有内容:Java 来自其他线程的JTA事务(之前的JSR-236),java,multithreading,jpa,javabeans,jta,Java,Multithreading,Jpa,Javabeans,Jta,我的JavaEE应用程序应该有一个后台线程,用于更新DB状态。为此,我想使用JPA。做这件事的最佳实践是什么?我们的EE容器是之前的JSR-236,所以ManagedExecutorService不是我们的选择 顺便说一句,我尝试了下面的代码,但它没有工作-没有抛出异常,但没有保存到DB中。没有后台线程并使用注入的EntityManager保存所有内容: @Singleton public class IdentityDao{ @PersistenceUnit(unitName = "
@Singleton
public class IdentityDao{
@PersistenceUnit(unitName = "routing")
private EntityManagerFactory emf;
@Resource
private UserTransaction utx;
@PostConstruct
protected void startConverter() {
new Converter();
}
private class Converter implements Runnable {
private Converter() {
ScheduledExecutorService scheduler = ThreadUtils.newSingleThreadScheduledExecutor("test", true);
scheduler.scheduleAtFixedRate(this, 5, 5, TimeUnit.SECONDS);
}
@Override
public void run() {
EntityManager em = emf.createEntityManager();
try {
utx.begin();
em.persist(new PersonEntity("123"));
utx.commit();
} catch (Exception e) {
try {
e.printStackTrace();
utx.rollback();
} catch (Exception exc) {
}
} finally {
em.close();
}
}
}
}
最后我找到了简单的解决办法。正如Gimby所建议的,它基于ejb定时器的使用
@Singleton
public class IdentityDao{
@PersistenceContext
EntityManager em;
@Schedule(hour = "*", minute = "*", second = "*/10")
public void every10Sec() {
em.persist(new PersonEntity("123"));
}
}
如果您有EntityManager,那么为什么要使用UserTransaction?使用EntityManager!实体管理器的问题在于它需要事务。当您编写em.getTransaction.begin时,它会抛出类似sorry的异常,但在JTA模式下,只有JTA事务是可能的。UserTransaction是一个JTA事务,所以在上面的代码中没有抛出异常,但是DB状态无论如何都不会改变。我不知道ThreadUtils做了什么。它是使用JEE ManagedScheduledExecutorService还是标准的JSE ScheduledExecutorService?您应该在JEE环境中使用前者,因此它实际上是容器管理的。似乎我们的web容器太旧,无法提供JSR-236功能,所以我们需要一些旧的解决方案。我同意,您应该研究一下。可能是经典的EJB计时器服务。PS:您应该在实际问题中添加一些重要的细节,比如在遗留技术上运行。