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

Java WebServices com BD

Olá Pessoal,

Dando continuidade aos post sobre webservice neste ultimo desta série, vamos ver como ter uma aplicação que faz pesquisa no banco de dados e vamos disponibilizar essa pesquisa via webservice. Um cliente nosso, vai consumir essa webservice e conseguir pesquisar em nosso banco, então deixar o “hello world” de lado. Ah, vamos usar o Hibernate framework para fazer a consultar no banco.Outro detalhe, não seguir as melhores praticas para criar  DAO genérica, fiz tudo em uma classe, o objetivo aqui não é DAO, Hibernate etc. E sim disponibilizar um web service para que possa ser consumido pelos clientes, que será uma consulta de clientes pelo ID.

Lets go…

Requisitos

  • Java 6 ou mais recente
  • MySql 5
  • Hibernate

Contexto

Se você não entendeu bem o contexto, vou dar um pouco mais de detalhe, antes de começarmos a desenvolver. Vamos ter dois projetos, um que é a nossa aplicação que pesquisa clientes por ID e o outro o projeto do fornecedor que vai consumir a webservice. O nosso banco já está populado com alguns clientes. No nosso caso serão poucos dados apenas o ID e o CPF.

Desenvolvendo

Nosso código será um pouco grande, pois vou incluir parcialmente o código do Hibernate,  também vou considerar que já conhece o framework, sendo assim, não irei explicar código que não seja relacionado webservice. Se tem dúvida com o Hibernate, pode visitar nossa categoria aqui no blog e ver o que temos por lá.  Certifique-se também que você tem uma tabela no banco populada:

A minha tabela chamei de Cliente.

Crie o projeto Java Project aqui chamei de WSDAO.

Não esqueça de adicionar os .jars do Hibernate  & MySQL ao seu projeto.

Vamos começar pelo bean, então crie uma classe cliente conforme abaixo, os getters/setters foram omitidos.

@Table

@Entity

public class Cliente {

      @Id

      @Column(name=”ID_CLIENTE”)

      @GeneratedValue

      private int id;

      @Column

      private long cpf;

//getters/setters omitidos

Agora vamos criar o nosso DAO, para isso crie uma classe conforme abaixo:

public class ClienteDAO {

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

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

      public Session getSession(){

            Session session = threadLocal.get();

            if (session == null) {

                  session = sessionFactory.openSession();

                  threadLocal.set(session);

            }

            return session;

      }

      public Cliente getCliente(int id) {

            Session session = getSession();

            Cliente cliente = new Cliente();

            try{

                  session.beginTransaction();

            String hql = “from Cliente where id=:idvalue “;

            Query query = session.createQuery(hql );

                  query.setInteger(“idvalue”, id);

                  cliente = (Cliente) query.uniqueResult();

            }catch (HibernateException e) {

                  e.printStackTrace();

            }finally{

                  session.close();

            }

            return cliente;

      }

Criando agora o nosso SEI:

@WebService

public interface Service {

      @WebMethod

      Cliente getCliente(int id);

}

Criando SIB

@WebService(endpointInterface=”br.com.camilolopes.ws.sei.Service”)

public class ServiceImpl implements Service {

      private ClienteDAO clienteDAO = new ClienteDAO();

      @Override

      public Cliente getCliente(int id) {

            return clienteDAO.getCliente(id);

      }

}

Publicando o serviço:

public class ClientePublish {

      public static void main(String[] args) {

            Endpoint.publish(“http://localhost:9876/wscliente”, new ServiceImpl());

      }

}

Testando com SOAPUI

            Agora precisamos testar, então suba o serviço rodando a classe ClientePublish(Run → as    → Java Application ) e em seguida abra o SOAPUI, crie um projeto e passe a url do  com o wsdl (no meu caso: http://localhost:9876/wscliente?wsdl)

            Ao adicionar url certamente verá o método getCliente a esquerda na tela da esquerda da ferramenta, click no sinal + e dê dois cliques no request1. Sua tela deve ser conforme a image a seguir:

Na tag <arg0>?</arg0> vamos passar o ID do cliente que queremos buscar, então informe os Ids válidos conforme vimos mais cedo na tabela do DB. Vou informar o ID 1 e ele deve retornar o resultado na aba que está a esquerda. Troque a  ? por 1 e execute clicando no botão submit request (uma seta verde que está na parte superior da tela)

note: lembre-se que seu serviço deve tá publicado, ou seja, a classe que faz o publish deve tá rodando. No caso do exemplo do post chamei ela de ClientePublish.

O resultado é conforme a imagem a seguir:

Observe que temos o resultado no formato XML a direita. E  oque acontece se o ID  não existir? Simplesmente não traz nada. :).

Criando o Cliente para Consumir

Agora vamos criar um cliente que vai conseguir esse nosso webservice  que faz uma pesquisa no banco de dados pelo ID do cliente. Para ficar claro e separar o projeto webservice do cliente, vamos criar um projeto separado, lembrando que uma vez o serviço publicado este projeto cliente que vai consumir o webservice, não necessariamente precisa ser desenvolvido em Java, poderia ser em .NET, PHP etc.

Step 1

Crie um novo projeto Java, o do post chamei de WSDAOConsumer somente para facilitar o entendimento no post.

note: não crie os packages conforme a imagem acima, apenas o projeto por enquanto, beleza?

Step 2

            via prompt de comando acesse o src do projeto

Step 3

            import o wsdl para o projeto:

wsimport -keep -p br.ws.cliente http://localhost:9876/wscliente?wsdl

note: Se você não quiser rodar o comando wsimport verifique se a sua IDE dá suporte  na importação do wsdl de maneira visual e execute, o resultado será o mesmo. Depender da versão do Eclipse que estiver usando você terá o suporte.

Step 4

            crie em um package separado a classe que vai usar as operações do service

public class Consumer {

      public static void main(String[] args) {

            Service service = new ServiceImplService().getServiceImplPort();

                  Cliente cliente = service.getCliente(1);

                  System.out.println(cliente.getId());

                  System.out.println(cliente.getCpf());

      }

}

O resultado é mais simples possível, apenas imprime o resultado no console:

A questão é: “imprime no console, porque o meu projeto é assim, ele usa o prompt para imprimir as coisas que ele consome do web service”.Analise e pense dessa forma com o exemplo acima.Porém, Se fosse um projeto JEE eu poderia exibir isso em uma view JSF em uma tabela ou também não poderia exibir em lugar nenhum, e pegar o resultado do WS e salvar em tabela no meu banco de dados, enfim são N possibilidades que podemos fazer com os dados que estamos consumindo, isso vai está atrelado as regras de negócio do seu projeto. Resolvi trazer essa abordagem, para quem está chegando não ache que para consumir um web service deve rodar em cima de Java Application apenas.

Vou ficando por aqui, espero que vocês tenham gostado dessa  série de posts sobre web service.

Abraços, see ya!!

Hibernate Schema Diferente via Java Project

olá Pessoal,

Este post é levemente diferente do que vimos no Mapeando schemas diferentes com o Hibernate. Lá tivemos que criar um bean para representar à tabela, neste aqui vamos usar um mapeamento para tabela já existente, assim evitamos de ter dois beans para uma mesma tabela.

Lets go…

Contexto

No post Mapeando schemas diferentes com o Hibernate assumimos que não existia nenhuma projeto Java que usasse o schema ereaders. Mas, no contexto de hoje vamos supor que tenha um outro projeto que use e já tenha os devidos mapeamentos para a tabela ereaders.usuario e não queremos ter que criar um novo bean em nosso projeto só para ler esse schema, pensamos em aproveitar o mapeamento já feito e usá-lo. Isso nos ajuda até em não ter que ficar atualizando cada bean, caso algum atributo da tabela venha sofrer alteração. Então temos os seguintes projetos Java:

O projeto sem enumeração é o que tem o mapeamento usando annotations para tabela que está em ereaders. Como usar esse bean em outro projeto java?

Muito simples, basta adicionarmos ao projeto HibernateSchema2 uma dependencia com o projeto HibernateSchema. Assim, podemos acessar as classes disponiveis naquele projeto. Para fazer isso, clique com o botão direito do projeto >> build path >> configure build path e adicione o projeto HibernateSchema, conforme a imagem a seguir:

No arquibo hibernate.cfg.xml informamos a classe nova que o projeto deve reconhecer via Hibernate:

< mapping class=“br.com.camilolopes.bean.Usuarios”/ >

Testando

Faremos algo semelhante ao que vimos no outro post, vamos ler dados da tabela e imprimir o valor em seguida, porém vamos usar Criteria API:

publicclass UserDAO extends DAO {

publicList getListUsers(){

begin();

Criteria criteria = getSession().createCriteria(Usuarios.class);

return criteria.list();

}

}

Na classe main, adicionamos o codigo:

publicstaticvoid main(String[] args) {

UserDAO userDAO = new UserDAO();

List<Usuarios> listUsers = userDAO.getListUsers();

for (Usuarios usuarios : listUsers) {

System.out.println(usuarios.getEmail()); } }

O resultado:

Nada de novo, o mesmo resultado que tivemos no outro post. Mas, qual a diferença? Veremos isso com base no que pode ser “problema” em alguns projetos.

Problema

  • um dos problemas é ter dependência com outro projeto, ou seja, se o outro não buildar/compilar o seu ficará preso. E isso em alguns cenários pode ser ruim. Depende da relação entre os projetos.

Vantagem

  • você não precisa ter mais dois beans para mesma tabela, então tudo é focado apenas no bean que já está no outro projeto, caso esta sofra alterações não preciso mudar no projeto HibernateSchema2. E evita essas duplicações de beans.

Qual usar?

Como falei, não há segredo, e sim necessidade, o que seu projeto importa mais? O que for mais importante é o que vai precisar.

Vou ficando por aqui espero que tenham gostado do post.

Abracos, see ya! 

selectOneMenu JSF com BD

olá Pessoal,

Hoje vou mostrar como criar preencher um selectOneMenu com dados vindo do Banco de Dados. Há várias formas de fazer isso, no blog o rponte você vai ver alguns posts bem interessante sobre o assunto. Vou mostrar abaixo como deixar seu selectOneMenu dinâmico pegando os dados do BD.

Tive como referência o livro do autor Edson Gonçalves em seu livro Dominando JSF.

lets go…

Posts Recomendados

Note: Para o exemplo a seguir usei o Hibernate puro para persistência e o TomCat 6 como servidor.

Preparando o ambiente:

  1. crie seu projeto JSF e sua página jsp ou xhtml

Aqui vamos usar xhtml, mas nada impede de usar .jsp o código JSF não vai mudar se vc criou um dos dois arquivos acima.

  1. Não esqueça de criar uma tabela no seu banco de dados. Aqui chamamos ela de cargo

Desenvolvendo

  1. Na sua classe DAO, crie um método que vai retornar todos cargos cadastrados:

    //retorna todos os cargos cadastrados
    	public List listaCargo(){
    		Query query = getSession().createQuery("from Cargo");
    		Listlista = query.list(); 
    
    		return lista;
    	}
  2. Na ControllerCargo você deve ter o método e a variável abaixo.

    public class ControllerCargo {
    	private Cargo cargo;
    	private Map cargoitem=null;
    	private ListDataModel model; 
    
    	public ControllerCargo() {
    		cargo = new Cargo();
    	}
    //outros codes foram omitidos, pois não tem importância para o objetivo do post
    
    //será armazenado no selectOneMenu
    	public Map getCargos(){
    	CargoDAO cargodao = new CargoDAO();
    	cargoitem = new LinkedHashMap();
    	for(Iterator iter =cargodao.listaCargo().iterator();iter.hasNext();){
    	Cargo c = (Cargo) iter.next();
    	 //armazenando os cargos encontrados no bd em um map
    		cargoitem.put(c.getFuncao(), c.getFuncao());
    	}
    	return cargoitem;}
  3. Essa aqui é nossa classe cargo:

    public class Cargo {
    	private int id;
    	private String funcao;
    	private String area;
    //gets/sets omitidos
  4. criamos uma página em xhtml (poderia ser em JSP) que tem o selectOneMenu carregado com os cargos que estao na tabela no BD, veja como ficou o code:
<input jsfc=”h:selectOneMenu” value=”#{controllerUser.usuario.funcao}” >
<f:selectItems value=”#{controllerCargo.cargos}” />
</input>

<input jsfc=”h:selectOneMenu” value=”#{controllerUser.usuario.funcao}” >

<f:selectItems value=”#{controllerCargo.cargos}” />

</input>


    Erro comum

    1. um erro comum é não prestar atencao no S que temos entre selectItems e seletecItem, se vc deixar no singular, terá problemas ao executar a página. Afinal de contas você informou que vai receber uma coleção de dados.

    Teste

    Veja abaixo o exemplo do selectOneMenu pegando informações que vem do BD. temos um formulário e logo a seguir um select do banco de dados.

    selectonebdjsf

    Vou ficando por aqui pessoal e até a proxima, espero que tenham gostado, o objetivo aqui foi apresentar um ponto bem especifico, por isso não coloquei todo o código para não perder o foco. Até porque nada mudou nas outras classes.

    Abracos, see you next post.