package org.needle4j.db.transaction; import java.util.List; import javax.persistence.Entity; import javax.persistence.EntityManager; /** * Utility class to manage transactions conveniently. */ public class TransactionHelper { private final EntityManager entityManager; public TransactionHelper(final EntityManager manager) { this.entityManager = manager; } /** * Saves the given object in the database. * * @param <T> * type of given object obj * @param obj * object to save * @return saved object * @throws Exception * save objects failed */ public final <T> T saveObject(final T obj) throws Exception { return executeInTransaction(new Runnable<T>() { @Override public T run(final EntityManager entityManager) { return persist(obj, entityManager); } }); } /** * Finds and returns the object of the given id in the persistence context. * * @param <T> * type of searched object * @param clazz * type of searched object * @param id * technical id of searched object * @return found object * @throws Exception * finding object failed */ public final <T> T loadObject(final Class<T> clazz, final Object id) throws Exception { return executeInTransaction(new Runnable<T>() { @Override public T run(final EntityManager entityManager) { return loadObject(entityManager, clazz, id); } }); } /** * Returns all objects of the given class in persistence context. * * @param <T> * type of searched objects * @param clazz * type of searched objects * @return list of found objects * @throws IllegalArgumentException * if the instance is not an entity * @throws Exception * selecting objects failed */ public final <T> List<T> loadAllObjects(final Class<T> clazz) throws Exception { final Entity entityAnnotation = clazz.getAnnotation(Entity.class); if (entityAnnotation == null) { throw new IllegalArgumentException("Unknown entity: " + clazz.getName()); } return executeInTransaction(new Runnable<List<T>>() { @Override @SuppressWarnings("unchecked") public List<T> run(final EntityManager entityManager) { final String fromEntity = entityAnnotation.name().isEmpty() ? clazz.getSimpleName() : entityAnnotation .name(); final String alias = fromEntity.toLowerCase(); return entityManager.createQuery("SELECT " + alias + " FROM " + fromEntity + " " + alias) .getResultList(); } }); } /** * Encapsulates execution of runnable.run() in transactions. * * @param <T> * result type of runnable.run() * @param runnable * algorithm to execute * @param clearAfterCommit * <tt>true</tt> triggers entityManager.clear() after transaction * commit * @return return value of runnable.run() * @throws Exception * execution failed */ public final <T> T executeInTransaction(final Runnable<T> runnable, final boolean clearAfterCommit) throws Exception { T result; try { entityManager.getTransaction().begin(); result = runnable.run(entityManager); entityManager.flush(); entityManager.getTransaction().commit(); if (clearAfterCommit) { entityManager.clear(); } } finally { if (entityManager.getTransaction().isActive()) { entityManager.getTransaction().rollback(); } } return result; } /** * see executeInTransaction(runnable, clearAfterCommit) . * * @param <T> * result type of runnable.run() * @param runnable * algorithm to execute * @return return value of runnable.run() * @throws Exception * execution failed */ public final <T> T executeInTransaction(final Runnable<T> runnable) throws Exception { return executeInTransaction(runnable, true); } public final EntityManager getEntityManager() { return entityManager; } public <T> T persist(final T obj, final EntityManager entityManager) { entityManager.persist(obj); return obj; } public <T> T persist(final T obj) { return persist(obj, entityManager); } public <T> T loadObject(final EntityManager entityManager, final Class<T> clazz, final Object id) { return entityManager.find(clazz, id); } }