Olá galera, li um tópico do GUJ sobre dao’s nas classes de negocio, e sobre o pattern repository, mas alguma coisas ainda não ficaram claras, então resolvi postar o meu modelo de arquitetura para ver o que vocês acham.
Ele está definido da seguinte forma
WEB > Action > DAO > Implementacao DAO > Banco
Segue o modelo dos DAO’s
public interface Dao <T> {
public T get(Serializable id) throws DAOException;
public void save(T entidade) throws SaveException;
public T update(T entidade) throws UpdateException;
public void delete(Serializable id) throws DeleteException;
public List<T> findAll() throws QueryException;
public List<T> findAll(final Integer primeiro, final Integer maxino) throws QueryException;
}
AbstractDao
@SuppressWarnings("unchecked")
public abstract class AbstractDao<T> implements Dao<T>{
private EntityManager em;
private Map<String, Object> parametros = new HashMap<String,Object>();
private String declaracao;
public AbstractDao(){
em = JPAFilter.getEm(); //Filtro Global de controle de transaction, invocado pelo Mentawai
}
public final EntityManager getEm() {
return em;
}
public void setEm(EntityManager em) {
this.em = em;
}
protected abstract Class<T> getDefineClass() ;
public T get(Serializable id) throws DAOException{
try{
T entidade = (T) getEm().find(getDefineClass(), id);
return entidade;
}catch (Exception e) {
throw new DAOException(e.getMessage());
}
}
public void save(T entidade) throws SaveException {
try{
getEm().persist(entidade);
// getEm().flush();
}catch (Exception e) {
throw new SaveException(e.getMessage());
}
}
public T update(T entidade) throws UpdateException {
try{
if(entidade == null){
throw new SaveException("Objeto nulo para update");
}
preUpdate(entidade);
return getEm().merge(entidade);
}catch (Exception e) {
throw new UpdateException(e.getMessage());
}
}
public void delete(Serializable id) throws DeleteException {
try{
if(id == null){
throw new DeleteException("Objeto nulo para deleção");
}
getEm().remove(get(id));
}catch (Exception e) {
throw new DeleteException(e.getMessage());
}
}
protected final void addParametros(String key, Object value) {
parametros.put(key, value);
}
protected final void addParametros(Integer key, Object value) {
addParametros(String.valueOf(key), value);
}
protected final void limpaParametros() {
parametros.clear();
}
protected final void setDeclaracao(String declaracao) {
this.declaracao = "FROM "+getDefineClass().getName()+" "+declaracao;
}
public List<T> findAll() throws QueryException {
try{
setDeclaracao("");
return find();
}catch (Exception e) {
throw new QueryException(e.getMessage());
}
}
public List<T> findAll(Integer primeiro, Integer maximo) throws QueryException {
try{
setDeclaracao("");
return find(primeiro, maximo);
}catch (Exception e) {
throw new QueryException(e.getMessage());
}
}
protected List<T> find() throws QueryException {
try{
return find(0, 0);
}catch (Exception e) {
throw new QueryException(e.getMessage());
}
}
protected List<T> find(Integer primeiro, Integer maximo) throws QueryException {
try{
Query query = getEm().createQuery(declaracao);
addParamQuery(query);
List result = null;
try {
if(primeiro != 0){
query.setFirstResult(primeiro);
}
if(maximo != 0){
query.setMaxResults(maximo);
}
result = query.getResultList();
if (result.isEmpty()) {
throw new Exception();
}
} catch (Exception e) {
throw new QueryException("Nenhuma informacao encontrada!");
}
return result;
}catch (Exception e) {
throw new QueryException(e.getMessage());
}
}
private void addParamQuery(Query query) throws QueryException {
try{
for (Iterator it = parametros.entrySet().iterator();it.hasNext();) {
Entry entry = (Entry) it.next();
try {
query.setParameter(Integer.parseInt((String) entry.getKey()),entry.getValue());
} catch (NumberFormatException e) {
query.setParameter((String) entry.getKey(), entry.getValue());
} catch (Exception e1) {
throw new QueryException(e1.getMessage());
}
}
parametros.clear();
}catch (Exception e) {
throw new QueryException(e.getMessage());
}
}
public Long selectCount() throws QueryException{
try{
Long count = -1L;
try{
Query query = getEm().createQuery("SELECT COUNT(*) "+declaracao);
count = (Long) query.getSingleResult();
}catch (Exception e) {
throw new QueryException(e.getMessage());
}
return count;
}catch (Exception e) {
throw new QueryException(e.getMessage());
}
}
public List<T> findByExample(T example) throws QueryException {
return findByExample(example, 0, 0);
}
public List<T> findByExample(T example, Integer primeiro, Integer maximo) throws QueryException {
final Session session = (Session) getEm().getDelegate();
final Criteria c = session.createCriteria(getDefineClass());
Example e = Example.create(example).enableLike(MatchMode.ANYWHERE);
c.add(e);
addOrderToCriteria(c);
if(primeiro != 0){
c.setFirstResult(primeiro);
}
if(maximo != 0){
c.setMaxResults(maximo);
}
return c.list();
}
public T findOneByExample(T example) throws QueryException {
final List<T> result = findByExample(example, 0, 1);
if(result != null && !result.isEmpty()){
return result.get(0);
}else{
return null;
}
}
public Integer selectCountByExample(T example) throws QueryException {
try{
Integer count = -1;
try{
count = findByExample(example).size();
}catch (Exception e) {
throw new QueryException(e.getMessage());
}
return count;
}catch (Exception e) {
throw new QueryException(e.getMessage());
}
}
public Session getSession() {
return (Session) getEm().getDelegate();
}
protected void preUpdate(T entidade) throws UpdateException {}
protected void addOrderToCriteria(Criteria criteria){}
}
Ai por exemplo quando eu vou criar um UsuarioDAO , eu crio uma interface UsuarioDAO deste jeito:
public interface UsuarioDao extends Dao<Usuario> {
public Usuario getPorLogin(String login) throws QueryException;
}
Ai tenho a implementação do DAO definida assim:
public class UsuarioDaoImpl extends AbstractDao<Usuario> implements UsuarioDao {
protected Class<Usuario> getDefineClass() {
return Usuario.class;
}
public Usuario getPorLogin(String login) throws QueryException {
setDeclaracao("where login=?");
addParametros(1, login);
return find().iterator().next();
}
}
A action abstrata fica definida assim:
@SuppressWarnings("unchecked")
public abstract class AbstractAction <T> extends BaseAction {
private static final Logger log = Logger.getLogger(AbstractAction.class);
private T bean = null;
public T getBean() {
return bean;
}
public void setBean(T bean) {
this.bean = bean;
}
protected abstract Dao<T> getDao();
.....
Ai quando quero criar uma action herdo de AbstractAction, e reescrevo o método abstrato getDao, que retorna o dao correspondente que minha action tem como atributo, injetado via IOC.
Ex:
public class UsuarioAction extends AbstractAction<AbstractUser> {
private UsuarioDao usuarioDao; //Populado via filtro global de IOC
protected Dao<AbstractUser> getDao() {
return usuarioDao;
}
}
O que acham deste modelo, gostaria de opiniões sobre como posso melhorar, dicas sugestões, etc…
Grato