GenericDaoImpl.java
package net.bryansaunders.jee6divelog.dao;
/*
* #%L
* BSNet-DiveLog
* $Id:$
* $HeadURL:$
* %%
* Copyright (C) 2012 Bryan Saunders
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-3.0.html>.
* #L%
*/
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.List;
import javax.ejb.Stateless;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
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 net.bryansaunders.jee6divelog.model.DiveLogEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Implementation of Generic DAO.
*
* @author Bryan Saunders <btsaunde@gmail.com>
*
* @param <T>
* Entity type for DOA, Must exted DiveLogEntity
*/
@Stateless
public class GenericDaoImpl<T extends DiveLogEntity> implements GenericDao<T> {
/**
* Logger.
*/
private final Logger logger = LoggerFactory.getLogger(GenericDaoImpl.class);
/**
* Entity Manager.
*/
@Inject
private EntityManager entityManager;
/**
* Entity Class.
*/
private final Class<T> entityClass;
/**
* Default Constructor.
*/
@SuppressWarnings("unchecked")
public GenericDaoImpl() {
final ParameterizedType genericSuperclass = (ParameterizedType) this.getClass().getGenericSuperclass();
this.entityClass = (Class<T>) genericSuperclass.getActualTypeArguments()[0];
}
/**
* {@inheritDoc}
*/
@Override
public void setEntityManager(final EntityManager newEntityManager) {
this.entityManager = newEntityManager;
}
/**
* {@inheritDoc}
*/
@Override
public EntityManager getEntityManager() {
return this.entityManager;
}
/**
* {@inheritDoc}
*/
@Override
public T get(final Integer id) {
final T entity = this.entityManager.find(this.entityClass, id);
if (entity == null) {
throw new NoResultException("Entity Type: " + this.entityClass.getName() + " with ID: " + id
+ " Not Found.");
}
return entity;
}
/**
* {@inheritDoc}
*/
@Override
public List<T> get(final Integer... ids) {
if (ids == null || ids.length == 0) {
throw new IllegalArgumentException("ID List must not be null and have atleast one element");
}
final List<T> entityList = new ArrayList<T>(ids.length);
for (final Integer id : ids) {
final T entity = this.get(id);
entityList.add(entity);
}
return entityList;
}
/**
* {@inheritDoc}
*/
@Override
public List<T> getAll() {
final CriteriaBuilder criteriaBuilder = this.entityManager.getCriteriaBuilder();
final CriteriaQuery<T> criteriaQuery = criteriaBuilder.createQuery(this.entityClass);
final Root<T> root = criteriaQuery.from(this.entityClass);
criteriaQuery.select(root);
final TypedQuery<T> query = this.entityManager.createQuery(criteriaQuery);
return query.getResultList();
}
@Override
public T save(final T object) {
T savedObject = null;
if (object.getId() != null) {
this.logger.debug("Merging Object " + this.entityClass.getName() + " with ID " + object.getId());
savedObject = this.entityManager.merge(object);
} else {
this.logger.debug("Persisting Object " + this.entityClass.getName());
this.entityManager.persist(object);
savedObject = object;
this.logger.debug("Persisted with ID " + savedObject.getId());
}
return savedObject;
}
/**
* {@inheritDoc}
*/
@Override
public List<T> save(final T... objects) {
if (objects == null || objects.length == 0) {
throw new IllegalArgumentException("Object List must not be null and have atleast one element");
}
final List<T> entityList = new ArrayList<T>(objects.length);
for (final T entity : objects) {
final T savedEntity = this.save(entity);
entityList.add(savedEntity);
}
return entityList;
}
/**
* {@inheritDoc}
*/
@Override
public void delete(final Integer id) {
final T entity = this.get(id);
this.delete(entity);
}
/**
* {@inheritDoc}
*/
@Override
public void delete(final Integer... ids) {
if (ids == null || ids.length == 0) {
throw new IllegalArgumentException("Object List must not be null and have atleast one element");
}
for (final Integer id : ids) {
this.delete(id);
}
}
/**
* {@inheritDoc}
*/
@Override
public void delete(final T object) {
this.entityManager.remove(object);
this.logger.debug("Deleting Object " + this.entityClass.getName() + " with ID " + object.getId());
}
/**
* {@inheritDoc}
*/
@Override
public void delete(final T... objects) {
if (objects == null || objects.length == 0) {
throw new IllegalArgumentException("Object List must not be null and have atleast one element");
}
for (final T entity : objects) {
this.delete(entity);
}
}
/**
* {@inheritDoc}
*/
@Override
public void deleteAll() {
final List<T> entities = this.getAll();
for (final T entity : entities) {
this.delete(entity);
}
}
/**
* {@inheritDoc}
*/
@Override
public List<T> findByExample(final T example) {
final CriteriaBuilder criteriaBuilder = this.entityManager.getCriteriaBuilder();
// Build the Query
final CriteriaQuery<T> criteriaQuery = criteriaBuilder.createQuery(this.entityClass);
final Root<T> root = criteriaQuery.from(this.entityClass);
// Select all Columns
criteriaQuery.select(root);
// Build Where Clause
Predicate predicate = criteriaBuilder.conjunction();
final Field[] fields = this.entityClass.getDeclaredFields();
for (final Field field : fields) {
final String fieldName = field.getName();
// So that we ignore fields like jacocoData that get added by jacoco
if (fieldName.startsWith("$")) {
continue;
}
Object fieldValue = null;
try {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
field.setAccessible(true);
return null;
}
});
fieldValue = field.get(example);
} catch (final IllegalArgumentException e) {
this.logger.warn(
"findByExample Skipping Field " + fieldName + " on Object Type " + this.entityClass.getName()
+ ".", e);
continue;
} catch (final IllegalAccessException e) {
this.logger.warn(
"findByExample Skipping Field " + fieldName + " on Object Type " + this.entityClass.getName()
+ ".", e);
continue;
}
if (fieldValue != null) {
this.logger.info("Setting Where: " + fieldName + " = " + fieldValue.toString());
predicate = criteriaBuilder.and(predicate, criteriaBuilder.equal(root.get(fieldName), fieldValue));
}
}
criteriaQuery.where(predicate);
final TypedQuery<T> query = this.entityManager.createQuery(criteriaQuery);
this.logger.info("QUERY: " + query.toString());
return query.getResultList();
}
}