/*
* Copyright (C) 2015 Arthur Gregorio, AG.Software
*
* 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/>.
*/
package br.com.webbudget.domain.model.repository;
import br.com.webbudget.application.producer.qualifier.DefaultDatabase;
import br.com.webbudget.domain.model.entity.IPersistentEntity;
import java.util.List;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import javax.persistence.EntityManager;
import javax.persistence.LockModeType;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import org.hibernate.Criteria;
import org.hibernate.Session;
/**
* A implementacao padrao do repositorio generico, com esta classe habilitamos o
* suporte as funcionalidades basicas de um repositorio de dados no banco
*
* @param <T> a classe persistente para este repositorio
* @param <ID> o tipo de nossos ID
*
* @author Arthur Gregorio
*
* @version 1.1.0
* @since 1.0.0, 03/03/2013
*/
public abstract class GenericRepository<T extends IPersistentEntity, ID extends Serializable>
implements IGenericRepository<T, ID>, Serializable {
@DefaultDatabase
@PersistenceContext
private EntityManager entityManager;
private final Class<T> persistentClass;
/**
* Inicia o repositorio identificando qual e a classe de nossa entidade, seu
* tipo {@link Class<?>}
*/
@SuppressWarnings({"unchecked", "unsafe"})
public GenericRepository() {
this.persistentClass = (Class< T>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
}
/**
* @return nosso entityManager, inicializado e configurado
*/
protected EntityManager getEntityManager() {
if (this.entityManager == null) {
throw new IllegalStateException("The entityManager is not initialized");
}
return this.entityManager;
}
/**
* @return a {@link Criteria} do hibernate setada para a classe do
* repositorio
*/
protected Criteria createCriteria() {
return this.getSession().createCriteria(this.getPersistentClass());
}
/**
* @return a {@link Session} do Hibernate para que possamos usar nossa
* {@link Criteria} para buscas
*/
protected Session getSession() {
return (Session) this.getEntityManager().getDelegate();
}
/**
* @return a classe de nossa entidade persistente
*/
public Class<T> getPersistentClass() {
return this.persistentClass;
}
/**
* {@inheritDoc}
*
* @param id
* @param lock
* @return
*/
@Override
public T findById(ID id, boolean lock) {
final T entity;
if (lock) {
entity = (T) this.getEntityManager().find(
this.getPersistentClass(), id, LockModeType.OPTIMISTIC);
} else {
entity = (T) this.getEntityManager().find(
this.getPersistentClass(), id);
}
return entity;
}
/**
* {@inheritDoc}
*
* @return
*/
@Override
public List<T> listAll() {
final EntityManager manager = this.getEntityManager();
final CriteriaQuery<T> query = manager.getCriteriaBuilder()
.createQuery(this.getPersistentClass());
final TypedQuery<T> selectAll
= manager.createQuery(query.select(
query.from(this.getPersistentClass())));
return selectAll.getResultList();
}
/**
* {@inheritDoc}
*
* @return
*/
@Override
public Long count() {
final EntityManager manager = this.getEntityManager();
final CriteriaBuilder builder = manager.getCriteriaBuilder();
final CriteriaQuery<Long> query = builder.createQuery(Long.class);
query.select(builder.count(query.from(this.getPersistentClass())));
return manager.createQuery(query).getSingleResult();
}
/**
* {@inheritDoc}
*
* @param entity
* @return
*/
@Override
public T save(T entity) {
return this.getEntityManager().merge(entity);
}
/**
* {@inheritDoc}
*
* @param entity
*/
@Override
public void delete(T entity) {
final T persistentEntity = this.getEntityManager().getReference(
this.getPersistentClass(), entity.getId());
this.getEntityManager().remove(persistentEntity);
}
}