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<E extends TypedEntity<K>, K> implements
Dao<E, K>, Serializable {
private static final long serialVersionUID = 4998055731089977476L;
protected final Logger logger = LoggerFactory.getLogger(this.getClass());
@PersistenceContext
protected EntityManager entityManager;
protected Class<E> entity;
@SuppressWarnings("unchecked")
public GenericJpaDao() {
ParameterizedType genericSuperclass = (ParameterizedType) getClass()
.getGenericSuperclass();
Type type = genericSuperclass.getActualTypeArguments()[0];
if (type instanceof Class) {
this.entity = (Class<E>) type;
} else if (type instanceof ParameterizedType) {
this.entity = (Class<E>) ((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<E> findAll() {
return find(createSimpleQuery());
}
public List<E> findAll(int count) {
return find(createSimpleQuery(), count);
}
public List<E> findAll(int count, int offset) {
return find(createSimpleQuery(), count, offset);
}
public List<E> findAll(String sortColumn) {
return find(createSimpleQuery(), sortColumn);
}
public List<E> findAll(int count, String sortColumn) {
return find(createSimpleQuery(), count, sortColumn);
}
public List<E> findAll(int count, int offset, String sortColumn) {
return find(createSimpleQuery(), count, offset, sortColumn);
}
public List<E> findAll(String sortColumn, boolean isAscending) {
return find(createSimpleQuery(), sortColumn, isAscending);
}
public List<E> findAll(int count, String sortColumn, boolean isAscending) {
return find(createSimpleQuery(), count, sortColumn, isAscending);
}
public List<E> findAll(int count, int offset, String sortColumn, boolean isAscending) {
return find(createSimpleQuery(), count, offset, sortColumn, isAscending);
}
protected CriteriaBuilder getCriteriaBuilder() {
return entityManager.getCriteriaBuilder();
}
protected CriteriaQuery<E> createQuery() {
CriteriaQuery<E> c = getCriteriaBuilder().createQuery(this.entity);
return c;
}
protected CriteriaQuery<E> createSimpleQuery() {
CriteriaQuery<E> c = getCriteriaBuilder().createQuery(this.entity);
Root<E> root = c.from(this.entity);
c.select(root);
return c;
}
protected List<E> find(CriteriaQuery<E> query) {
return entityManager.createQuery(query).getResultList();
}
protected List<E> find(CriteriaQuery<E> query, int count) {
TypedQuery<E> q = entityManager.createQuery(query);
q.setMaxResults(count);
return q.getResultList();
}
protected List<E> find(CriteriaQuery<E> query, int count, int offset) {
TypedQuery<E> q = entityManager.createQuery(query);
q.setFirstResult(offset);
q.setMaxResults(count);
return q.getResultList();
}
protected List<E> find(CriteriaQuery<E> query, String sortColumn) {
return find(query, sortColumn, false);
}
protected List<E> find(CriteriaQuery<E> query, int count, String sortColumn) {
return find(query, count, sortColumn, false);
}
protected List<E> find(CriteriaQuery<E> query, int count, int offset, String sortColumn) {
return find(query, count, offset, sortColumn, false);
}
protected List<E> find(CriteriaQuery<E> query, String sortColumn, boolean isAscending) {
Root<E> root = query.from(this.entity);
if (isAscending) {
query.orderBy(getCriteriaBuilder().asc(root.get(sortColumn)));
} else {
query.orderBy(getCriteriaBuilder().desc(root.get(sortColumn)));
}
return entityManager.createQuery(query).getResultList();
}
protected List<E> find(CriteriaQuery<E> query, int count, String sortColumn, boolean isAscending) {
Root<E> root = query.from(this.entity);
if (isAscending) {
query.orderBy(getCriteriaBuilder().asc(root.get(sortColumn)));
} else {
query.orderBy(getCriteriaBuilder().desc(root.get(sortColumn)));
}
TypedQuery<E> q = entityManager.createQuery(query);
q.setMaxResults(count);
return q.getResultList();
}
protected List<E> find(CriteriaQuery<E> query, int count, int offset, String sortColumn, boolean isAscending) {
Root<E> root = query.from(this.entity);
if (isAscending) {
query.orderBy(getCriteriaBuilder().asc(root.get(sortColumn)));
} else {
query.orderBy(getCriteriaBuilder().desc(root.get(sortColumn)));
}
TypedQuery<E> q = entityManager.createQuery(query);
q.setFirstResult(offset);
q.setMaxResults(count);
return q.getResultList();
}
protected E findSingle(CriteriaQuery<E> query) {
return entityManager.createQuery(query).getSingleResult();
}
protected E findSingleOrNull(CriteriaQuery<E> 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<E> 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);
}
}
}