package dao.jpa;
import dao.Dao;
import dao.DataAccessException;
import models.Identifiable;
import models.entities.Contact;
import org.hibernate.Criteria;
import org.hibernate.Session;
import play.Logger;
import play.db.jpa.JPA;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.List;
/**
* Created by kiryl on 17.08.2014.
*/
public abstract class BaseJpaDao<T extends Identifiable<K>, K> implements Dao<T, K> {
protected Class entityClass;
public BaseJpaDao() {
ParameterizedType genericSuperclass = (ParameterizedType) getClass().getGenericSuperclass();
entityClass = (Class) genericSuperclass.getActualTypeArguments()[0];
}
@Override
public List<T> getList() throws DataAccessException{
try{
Session session = (Session) JPA.em().getDelegate();
Criteria criteria = session.createCriteria(entityClass);
return criteria.list();
}catch(Throwable throwable){
Logger.error("failed to get list of" + entityClass);
throw new DataAccessException("failed to get list of " + entityClass, throwable);
}
}
@Override
public void persist(T entity) throws DataAccessException {
try {
if (entity.getId() == null) {
JPA.em().persist(entity);
} else {
JPA.em().merge(entity);
}
JPA.em().flush();
} catch (Throwable throwable) {
Logger.error("failed to perist entity of class " + entityClass);
throw new DataAccessException("failed to perist entity of class " + entityClass, throwable);
}
}
@Override
public void remove(T entity) throws DataAccessException {
try {
JPA.em().remove(entity);
} catch (Throwable throwable) {
Logger.error("failed to remove entity of class " + entityClass);
throw new DataAccessException("failed to remove entity of class " + entityClass, throwable);
}
}
@Override
public T findById(K id) throws DataAccessException {
if (id == null) {
return null;
}
try {
return (T) JPA.em().find(entityClass, id);
} catch (Throwable throwable) {
Logger.error("failed to get by id " + id);
throw new DataAccessException("failed to get by id " + id, throwable);
}
}
@Override
public List<T> getBatch(int batchNumber, int batchSize) throws DataAccessException {
try {
CriteriaBuilder criteriaBuilder = JPA.em().getCriteriaBuilder();
CriteriaQuery<T> criteriaQuery = criteriaBuilder.createQuery(entityClass);
Root<T> from = criteriaQuery.from(entityClass);
CriteriaQuery<T> select = criteriaQuery.select(from);
TypedQuery<T> typedQuery = JPA.em().createQuery(select);
return getBatch(batchNumber, batchSize, typedQuery);
} catch (Throwable throwable) {
Logger.error("failed to get batch " + batchNumber + " of size " + batchSize);
throw new DataAccessException("failed to get batch " + batchNumber + " of size " + batchSize, throwable);
}
}
protected List<T> getBatch(int batchNumber, int batchSize, TypedQuery<T> typedQuery) throws Throwable {
if (batchNumber < 0 || batchSize < 1) {
return new ArrayList<T>();
}
typedQuery.setFirstResult(batchNumber * batchSize);
typedQuery.setMaxResults(batchSize);
List<T> entities = typedQuery.getResultList();
return entities;
}
@Override
public Integer totalEntities() throws DataAccessException {
try {
EntityManager em = JPA.em();
CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
CriteriaQuery<Long> countQuery = criteriaBuilder.createQuery(Long.class);
countQuery.select(criteriaBuilder.count(countQuery.from(entityClass)));
return Integer.valueOf((int)(long)(em.createQuery(countQuery).getSingleResult()));
} catch (Throwable throwable) {
Logger.error("failed to get batch entities count");
throw new DataAccessException("failed to get batch entities count", throwable);
}
}
}