/** * Run a block of code in a JPA transaction. * * @param name The persistence unit name * @param readOnly Is the transaction read-only? * @param block Block of code to execute */ public <T> T withTransaction(String name, boolean readOnly, Supplier<T> block) { EntityManager entityManager = null; EntityTransaction tx = null; try { entityManager = em(name); if (entityManager == null) { throw new RuntimeException("No JPA entity manager defined for '" + name + "'"); } JPA.bindForSync(entityManager); if (!readOnly) { tx = entityManager.getTransaction(); tx.begin(); } T result = block.get(); if (tx != null) { if (tx.getRollbackOnly()) { tx.rollback(); } else { tx.commit(); } } return result; } catch (Throwable t) { if (tx != null) { try { tx.rollback(); } catch (Throwable e) { } } throw t; } finally { JPA.bindForSync(null); if (entityManager != null) { entityManager.close(); } } }
/** * Run a block of asynchronous code in a JPA transaction. * * @param name The persistence unit name * @param readOnly Is the transaction read-only? * @param block Block of code to execute. * @deprecated This may cause deadlocks */ @Deprecated public <T> F.Promise<T> withTransactionAsync( String name, boolean readOnly, Supplier<F.Promise<T>> block) { EntityManager entityManager = null; EntityTransaction tx = null; try { entityManager = em(name); if (entityManager == null) { throw new RuntimeException("No JPA entity manager defined for '" + name + "'"); } JPA.bindForAsync(entityManager); if (!readOnly) { tx = entityManager.getTransaction(); tx.begin(); } F.Promise<T> result = block.get(); final EntityManager fem = entityManager; final EntityTransaction ftx = tx; F.Promise<T> committedResult = (ftx == null) ? result : result.map( t -> { if (ftx.getRollbackOnly()) { ftx.rollback(); } else { ftx.commit(); } return t; }); committedResult.onFailure( t -> { if (ftx != null) { try { if (ftx.isActive()) { ftx.rollback(); } } catch (Throwable e) { } } try { fem.close(); } finally { JPA.bindForAsync(null); } }); committedResult.onRedeem( t -> { try { fem.close(); } finally { JPA.bindForAsync(null); } }); return committedResult; } catch (Throwable t) { if (tx != null) { try { tx.rollback(); } catch (Throwable e) { } } if (entityManager != null) { try { entityManager.close(); } finally { JPA.bindForAsync(null); } } throw t; } }