package nu.xss.jpa.dao; import java.io.Serializable; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.List; import javax.persistence.EntityManager; import javax.persistence.NoResultException; import javax.persistence.NonUniqueResultException; import javax.persistence.PersistenceContext; import javax.persistence.TypedQuery; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Root; import nu.xss.jpa.entity.TypedEntity; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public abstract class GenericJpaDao, K> implements Dao, Serializable { private static final long serialVersionUID = 4998055731089977476L; protected final Logger logger = LoggerFactory.getLogger(this.getClass()); @PersistenceContext protected EntityManager entityManager; protected Class entity; @SuppressWarnings("unchecked") public GenericJpaDao() { ParameterizedType genericSuperclass = (ParameterizedType) getClass() .getGenericSuperclass(); Type type = genericSuperclass.getActualTypeArguments()[0]; if (type instanceof Class) { this.entity = (Class) type; } else if (type instanceof ParameterizedType) { this.entity = (Class) ((ParameterizedType)type).getRawType(); } } public void save(E entity) { logger.info("Persist Entity: {}.", entity.toString()); entityManager.persist(entity); logger.info("Saved entity: {}.", entity.toString()); } public void merge(E entity) { logger.info("Merge Entity: {}.", entity.toString()); entityManager.merge(entity); logger.info("Saved entity: {}.", entity.toString()); } public void delete(E entity) { E persistentEntity = findById(entity.getId()); entityManager.remove(persistentEntity); logger.info("Deleted entity: {}.", entity.toString()); } public E findById(K id) { return entityManager.find(entity, id); } public List findAll() { return find(createSimpleQuery()); } public List findAll(int count) { return find(createSimpleQuery(), count); } public List findAll(int count, int offset) { return find(createSimpleQuery(), count, offset); } protected CriteriaBuilder getCriteriaBuilder() { return entityManager.getCriteriaBuilder(); } protected CriteriaQuery createQuery() { CriteriaQuery c = getCriteriaBuilder().createQuery(this.entity); return c; } protected CriteriaQuery createSimpleQuery() { CriteriaQuery c = getCriteriaBuilder().createQuery(this.entity); Root root = c.from(this.entity); c.select(root); return c; } protected List find(CriteriaQuery query) { return entityManager.createQuery(query).getResultList(); } protected List find(CriteriaQuery query, int count) { TypedQuery q = entityManager.createQuery(query); q.setMaxResults(count); return q.getResultList(); } protected List find(CriteriaQuery query, int count, int offset) { TypedQuery q = entityManager.createQuery(query); q.setFirstResult(offset); q.setMaxResults(count); return q.getResultList(); } protected E findSingle(CriteriaQuery query) { return entityManager.createQuery(query).getSingleResult(); } protected E findSingleOrNull(CriteriaQuery query) { try { return findSingle(query); } catch (final NoResultException e) { return null; } catch (final NonUniqueResultException e) { logger.error("Found more than one result.. return first one"); return null; } } protected E findSingleFirstOrNull(CriteriaQuery query) { try { return findSingle(query); } catch (final NoResultException e) { return null; } catch (final NonUniqueResultException e) { logger.warn("Found more than one result.. return first one"); return find(query).get(0); } } }