java - 如何让try-finally中的finally等待线程完成?

标签 java jpa jpa-2.0 try-catch-finally try-finally

我在基于 Swing 的桌面应用程序中使用 JPA。这就是我的代码的样子:

public Object methodA() {

  EntityManager em = emf.createEntityManager();
  em.getTransaction().begin();
  boolean hasError = false;

  try {
       SwingUtilities.invokeLater(new Runnable() {
           public void run() {
              // JPA operation does not work here 
              // because transaction has been committed!
           }
       });
       ...
       return xXx;
  } catch (Exception ex) {
       hasError = true;
       em.getTransaction().rollback();
  } finally {
       em.close();
       if (!hasError) {
          em.getTransaction().commit();
       }
  }
  return null;    
}

我将这个 try - catch - finally 用于所有需要事务的方法。它按预期工作,但具有 SwingUtilities.invokeLater() 的方法除外。

finally 将在新线程中的所有代码执行完毕之前到达;因此,如果 SwingUtilities.invokeLater() 内部存在 JPA 操作,则会失败,因为事务已提交。

是否有一个 try - catch - finally 的通用用例,我可以遵循它来确保只有在执行所有代码(包括 SwingUtilities.invokeLater( 中的代码))后才会提交事务)

最佳答案

你必须重新考虑你的方法。首先,SwingUtilities.invokeLater() 并不是执行 JPA 操作的最佳选择。该实用程序方法的主要目的是更新 UI。关于您的代码,为 JPA 操作实现单独的线程,该线程将监听事务状态。交易完成后,您将更新 UI。

/**
 * Transaction callback.
 */
public interface TransactionListener {
    void onTransactionFinished(boolean hasError);
}

/**
 * Worker Thread which takes data and performs JPA operations.
 */
public class JPATask implements Runnable {
    private final Object dataToPersist;
    private final TransactionListener transactionListener;

    public JPATask(Object dataToPersist,
            TransactionListener transactionListener) {
        this.dataToPersist = dataToPersist;
        this.transactionListener = transactionListener;
    }

    private EntityManager getEntityManager() {/* code is omited */}

    @Override
    public void run() {
        EntityManager em = getEntityManager();
        try {
            em.getTransaction().begin();
            // perform JPA actions here
            em.getTransaction().commit();
            transactionListener.onTransactionFinished(false);
        } catch (Exception ex) {
            em.getTransaction().rollback();
            transactionListener.onTransactionFinished(true);
        }
    }
}

/**
 * Finally you method. Now it looks like this.
 */
public Object methodA() {
    JPATask jpaTask = new JPATask(<data to persist>, new TransactionListener() {
        @Override
        public void onTransactionFinished(boolean hasError) {
            // Update UI. It's time to use SwingUtilities.invokeLater() 
        }
    }).start();     
}

关于java - 如何让try-finally中的finally等待线程完成?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16404001/

相关文章:

java - java中的数组程序

java - 我可以使用 sql INSERT 语句插入 java 实体并稍后使用 JPQL 检索它吗?

hibernate - JPA 2.0 : Load a subset of fields for an entity

spring - Spring Data JPA @Query 是动态的还是命名的?

java - @Entity 无法识别@MappedSuperclass 中的@Id

java - 在 OneToMany 和 ManyToMany 映射中获取 StackOverflow

java - JPanel 不显示图形

java - Hibernate JPA 父子映射

java - Java 中的泛型在定义方法时抛出错误

jpa - 简单 JPA 2 条件查询 "where"条件