/** * This file is part of xss-jpa. * * Copyright 2012 Sebastian Schmelzer * http://xss.nu/ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with library. If not, see . * */ 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; /** * The Class GenericJpaDao. * * @param * the element type * @param * the key type */ public abstract class GenericJpaDao, K> implements Dao, Serializable { /** The Constant serialVersionUID. */ private static final long serialVersionUID = 4998055731089977476L; /** The logger. */ private Logger logger = LoggerFactory.getLogger(this.getClass()); /** The entity manager. */ @PersistenceContext private EntityManager entityManager; /** The entity. */ private Class entityClass; /** * Instantiates a new generic jpa dao. */ @SuppressWarnings("unchecked") public GenericJpaDao() { ParameterizedType genericSuperclass = (ParameterizedType) getClass() .getGenericSuperclass(); Type type = genericSuperclass.getActualTypeArguments()[0]; if (type instanceof Class) { this.entityClass = (Class) type; } else if (type instanceof ParameterizedType) { this.entityClass = (Class) ((ParameterizedType) type).getRawType(); } } @Override public void save(final E entity) { getEntityManager().persist(entity); logger.info("Saved entity: {}.", entity.toString()); } @Override public void merge(final E entity) { getEntityManager().merge(entity); logger.info("Updated unmanaged entity: {}.", entity.toString()); } @Override public void delete(final E entity) { final E persistentEntity = findById(entity.getId()); if (persistentEntity != null) { getEntityManager().remove(persistentEntity); } logger.info("Deleted entity: {}.", entity.toString()); } @Override public final E findById(final K id) { return getEntityManager().find(entityClass, id); } @Override public int count() { // TODO Auto-generated method stub return 0; } @Override public int count(final Filter... filter) { // TODO Auto-generated method stub return 0; } @Override public final List findAll() { return find(null, null, null); } @Override public final List findAll(final Sort sort) { return find(null, sort, null); } @Override public final List findAll(final Pagination pagination) { return find(null, null, pagination); } @Override public final List findAll(final Sort sort, final Pagination pagination) { return find(null, sort, pagination); } @Override public final List findAll(final Filter... filter) { return find(null, null, null, filter); } @Override public final List findAll(final Sort sort, final Filter... filter) { return find(null, sort, null, filter); } @Override public final List findAll(final Pagination pagination, final Filter... filter) { return find(null, null, pagination, filter); } @Override public final List findAll(final Sort sort, final Pagination pagination, final Filter... filter) { return find(null, sort, pagination, filter); } /** * Creates the query. * * @return the criteria query */ protected final CriteriaQuery createQuery() { CriteriaQuery c = getCriteriaBuilder().createQuery(this.entityClass); return c; } /** * Find. * * @param query * the query * @return the list */ protected final List find(final CriteriaQuery query) { return find(query, null, null); } /** * Find. * * @param query * the query * @param pagination * the pagination * @return the list */ protected final List find(final CriteriaQuery query, final Pagination pagination) { return find(query, null, pagination); } /** * Find. * * @param query * the query * @param sort * the sort * @return the list */ protected final List find(final CriteriaQuery query, final Sort sort) { return find(query, sort, null); } /** * Find. * * @param query * the query * @param sort * the sort * @param pagination * the pagination * @param filter * the filter * @return the list */ protected List find(final CriteriaQuery query, final Sort sort, final Pagination pagination, final Filter... filter) { Root root; CriteriaQuery q = query; // check if we have a 'simple' query if (q == null) { q = createQuery(); } root = q.from(getEntityClass()); q.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()) { q.orderBy(getCriteriaBuilder().asc(root.get(sort.getColumn()))); } else { q.orderBy(getCriteriaBuilder().desc(root.get(sort.getColumn()))); } } // Result pagination TypedQuery tq = getEntityManager().createQuery(q); // TODO: do we need to check cast long->int? if (pagination != null) { if (pagination.getCount() > 0) { tq.setMaxResults((int) pagination.getOffset()); } if (pagination.getOffset() > 0) { tq.setFirstResult((int) pagination.getCount()); } } return tq.getResultList(); } /** * Find single. * * @param query * the query * @return the e */ protected final E findSingle(final CriteriaQuery query) { return getEntityManager().createQuery(query).getSingleResult(); } /** * Find single or null. * * @param query * the query * @return the e */ protected final E findSingleOrNull(final 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; } } /** * Find single first or null. * * @param query * the query * @return the e */ protected final E findSingleFirstOrNull(final 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); } } /** * Gets the criteria builder. * * @return the criteria builder */ protected final CriteriaBuilder getCriteriaBuilder() { return getEntityManager().getCriteriaBuilder(); } /** * Gets the logger. * * @return the logger */ public final Logger getLogger() { return logger; } /** * Gets the entity manager. * * @return the entity manager */ public final EntityManager getEntityManager() { return entityManager; } /** * Sets the entity manager. * * @param entityManager the new entity manager */ public final void setEntityManager(final EntityManager entityManager) { this.entityManager = entityManager; } /** * Gets the entity class. * * @return the entity class */ public Class getEntityClass() { return entityClass; } }