package nu.xss.jpa.dao; import java.io.Serializable; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.HashSet; import java.util.List; import java.util.Set; 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.Predicate; import javax.persistence.criteria.Root; import nu.xss.jpa.entity.TypedEntity; import nu.xss.jpa.query.Pagination; import nu.xss.jpa.query.Sort; import nu.xss.jpa.query.filter.Filter; 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) { entityManager.persist(entity); logger.info("Saved entity: {}.", entity.toString()); } public void merge(E entity) { entityManager.merge(entity); logger.info("Updated unmanaged entity: {}.", entity.toString()); } public void delete(E entity) { final E persistentEntity = findById(entity.getId()); if (persistentEntity != null) { entityManager.remove(persistentEntity); } logger.info("Deleted entity: {}.", entity.toString()); } public E findById(K id) { return entityManager.find(entity, id); } @Override public int count() { // TODO Auto-generated method stub return 0; } @Override public int count(Filter... filter) { // TODO Auto-generated method stub return 0; } @Override public List findAll() { return find(null, null, null); } @Override public List findAll(Sort sort) { return find(null, sort, null); } @Override public List findAll(Pagination pagination) { return find(null, null, pagination); } @Override public List findAll(Sort sort, Pagination pagination) { return find(null, sort, pagination); } @Override public List findAll(Filter... filter) { return find(null, null, null, filter); } @Override public List findAll(Sort sort, Filter... filter) { return find(null, sort, null, filter); } @Override public List findAll(Pagination pagination, Filter... filter) { return find(null, null, pagination, filter); } @Override public List findAll(Sort sort, Pagination pagination, Filter... filter) { return find(null, sort, pagination, filter); } protected List find(CriteriaQuery query) { return find(query, null, null); } protected List find(CriteriaQuery query, Pagination pagination) { return find(query, null, pagination); } protected List find(CriteriaQuery query, Sort sort) { return find(query, sort, null); } protected List find(CriteriaQuery query, Sort sort, Pagination pagination, Filter... filter) { Root root; // check if we have a 'simple' query if (query == null) { query = createQuery(); } root = query.from(this.entity); query.select(root); if (filter != null) { Set predicates = new HashSet(); for (final Filter f: filter) { f.buildFilters(getCriteriaBuilder(), root); for (Predicate p : f.getPredicates()) { predicates.add(p); } } if (predicates.size() > 0) { query.where((Predicate[]) predicates.toArray()); } } // Result Sorting // TODO: Multcolum sort if (sort != null) { if (sort.isAsc()) { query.orderBy(getCriteriaBuilder().asc(root.get(sort.getColumn()))); } else { query.orderBy(getCriteriaBuilder().desc(root.get(sort.getColumn()))); } } // Result pagination TypedQuery q = entityManager.createQuery(query); if (pagination != null) { if ( pagination.getCount() > 0 ) { q.setFirstResult(pagination.getCount()); } if ( pagination.getOffset() > 0) { q.setMaxResults(pagination.getOffset()); } } 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); } } protected CriteriaBuilder getCriteriaBuilder() { return entityManager.getCriteriaBuilder(); } protected CriteriaQuery createQuery() { CriteriaQuery c = getCriteriaBuilder().createQuery(this.entity); return c; } }