Criando GenericDAO e DAOFactory em poucos passos

Ola pessoal,

No post de hoje vamos ver como criar genericDAO e DAOFactory  em poucos passos. O objetivo maior aqui é colocar a mão na massa. Os conceitos DAO Design Pattern não serão abordados, pois o que não falta é explicação na internet sobre o assunto. Vou considerar que você sabe conceitualmente um DAO, mas que nunca implementou  de forma genérica.

Lets go…

 

Primeiro passo

Cria a interface GenericDAO :

public interface GenericDAO<T,Type extends Serializable> {

void beginTransaction();

void commitTransaction();

void save(T entity);

void delete (T entity);

List<T> listAll();

}

O código acima usa apenas o recurso de generics do Java 5, deixando a interface que extends dizer qual será o tipo para T e o para Type.

O que significa cada um?

Simples: o T será a classe, ou seja, a entidade. O Type representará o tipo que usaremos para o Id da entidade. Você pode estar se perguntando pq a letra T e a palavra type. Apenas segui uma convenção, mas poderia ser qualquer outra letra ou nome.

Agora precisamos criar a interface dos nossos DAO, que nesse caso teremos as seguintes interfaces: ClientDAO e AccountDAO.

public interface AccountDAO extends GenericDAO<Account, Long>{

}

public interface ClientDAO extends GenericDAO<Client, Long> {

}

Observe que nas nossas interfaces é que definimos para qual entidade ela está associada e qual será o tipo do nosso ID.

É nessa interface que colocamos os métodos específicos para o nosso DAO.

Abstract HibernateDAO

Criaremos uma classe abstract que vai implementar o métodos abstract da interface GenericDAO. E nossas classes concentras vão extends a HibernateDAO como veremos a seguir. Mas antes disso precisamos criar uma classe utilitária que chamei de HibernateUtil, que terá o método para obtermos a sessão, iniciar a transação, commit, etc.

public class HibernateUtil {

private static SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();

private static ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();

public static Session getSession() {

Session session = threadLocal.get();

if (session == null) {

session = sessionFactory.openSession();

threadLocal.set(session);

}

return session;

}

public static void beginTransaction() {

getSession().beginTransaction();

}

 public static void commitTransaction() {

getSession().getTransaction().commit();

public static void rollBackTransaction() {

getSession().getTransaction().rollback();

}

public static void closeSession() {

getSession().close();

}

}

E na classe HibernateDao temos o código a seguir:

public abstract class HibernateDAO<T, Type extends Serializable> implements GenericDAO<T, Type>{

private Class<T> persistentClass;

public HibernateDAO(Class persistentClass) {

super();

this.persistentClass = persistentClass;

}

@Override

public void beginTransaction() {

HibernateUtil.beginTransaction();

}

@Override

public void commitTransaction() {

HibernateUtil.commitTransaction();

}

@Override

public void save(T entity) {

HibernateUtil.getSession().saveOrUpdate(entity);

}

@Override

public void delete(T entity) {

HibernateUtil.getSession().delete(entity);

}

@Override

public List<T> listAll() {

HibernateUtil.beginTransaction();

Criteria criteria = HibernateUtil.getSession().createCriteria(persistentClass);

return criteria.list();

}

}

Observe que implementamos todos os métodos da GenericDAO, assim a classe que extends já tem a implementation done, ou seja, aquilo que é comum para qualquer  classe DAO já vai estar implementado e disponível na classe pai.

Concrete DAO

Agora vamos criar a classe concreta que terá a implementação específica para cada DAO.

class HibernateClientDAO extends HibernateDAO<Client, Long> implements  ClientDAO {

public HibernateClientDAO(){

//                           we passing the entity for super class

super(Client.class);

}

}

Como não temos nada de específico para implementar da interface ClientDAO deixaremos o código assim. Observe que no construtor passei qual será o tipo T, que nesse caso será a class do Client.

DAOFactory

Agora vamos criar um DAOFactory que será responsável por criar as instâncias das classes Hibernate. A classe DAOFactory será abstract e tendo apenas um método implementado que será o getFactory, o qual terá como objetivo simplesmente de retornar uma instância da classe.

public abstract class DAOFactory {

private static final Class FACTORY_CLASS = HibernateDAOFactory.class;

public static DAOFactory getFactory(){

try {

return (DAOFactory) FACTORY_CLASS.newInstance();

} catch (InstantiationException e) {

// TODO Auto-generated catch block

throw new RuntimeException();

} catch (IllegalAccessException e) {

// TODO Auto-generated catch block

throw new RuntimeException();

}

}

public abstract ClientDAO getClientDAO();

public abstract AccountDAO getAccountDAO();

}

Em seguida adicionamos os métodos que retornam a instância para as classes que implementam as interfaces ClientDAO e AccountDAO.

Agora teremos uma classe que implementa os métodos do DAOFactory, que será a classe HibernateDAOFactory.

public class HibernateDAOFactory  extends DAOFactory{

@Override

public ClientDAO getClientDAO() {

return new HibernateClientDAO();

}

@Override

public AccountDAO getAccountDAO() {

return new HibernateAccountDAO();

}

}

Observe que apenas instanciamos as classes para cada DAO. Agora vamos criar  HibernateAccountDAO

class HibernateAccountDAO extends HibernateDAO<Account, Long> implements AccountDAO {

public HibernateAccountDAO() {

super(Account.class);

}

}

E para testar, criaremos uma classe com o método main:

public class MainBank {

public static void main(String[] args) {

//                           getting instance of the factory

DAOFactory daoFactory = DAOFactory.getFactory();

//                           getting intance of clientDAO and starting transaction

daoFactory.getClientDAO().beginTransaction();

ClientDAO clientDAO = daoFactory.getClientDAO();

Client client = new Client();

client.setName(“Camilo Lopes”);

//                           creating object of the entity

Account checkigAccount = new Account();

checkigAccount.setAccountType(AccountType.CHECKING_ACCOUNT);

//                           associate acocunt with the client

checkigAccount.setClient(client);

//                           money available in account

checkigAccount.setBalance(BigDecimal.ONE);

client.getAccount().add(checkigAccount);

//                           saveing in hibernate session

clientDAO.save(client);

AccountDAO accountDAO = daoFactory.getAccountDAO();

accountDAO.save(checkigAccount);

//                           commit

clientDAO.commitTransaction();

}

}

Resultado

É isso ai pessoal, espero que tenham gostado. Vou ficando por aqui. 

See ya!!!