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!!!