我在基于 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/