[Logo] Mentawai Forum - Mentawai Web Framework
  [Search] Search   [Recent Topics] Recent Topics   [Members]  Member Listing   [Groups] Back to home page 
[Register] Register / 
[Login] Login 

Forum Read-Only! Check the new site and forum here!

29) Como usar HibernateFilter com Annotations, IoC, DIFilter e Daos Genéricos.  XML
Forum Index -> F.A.Q.
Author Message
robertwgil


[Avatar]
Joined: 23/02/2007 17:22:13
Messages: 745
Location: São Paulo - SP - Brasil
Offline

Olá pessoal, ao ver muitos tópicos referentes ao uso do Hibernate com
Annotations via o filtro HibernateFilter, DAO genéricos, IoC e DI,
darei um exemplo simples ilustrando tal cenário.
Obs: Usarei um dao genérico simples apenas como exemplo.

Cenário, um simples cadastro de Países e Estados onde é cadastrado um
País e logo após um Estado relacionado ao País. ( Relacionamento 1x n ).


Primeiramente criaremos uma interface que será a nossa interface Base.

Interface BaseDao

Code:
 public interface BaseDao<T> {
     
     void delete(final T obj) throws Exception ;
     
     List<T> findByExample(final T example) throws Exception ;
     
     Serializable insert(T obj) throws Exception ;
     
     List<T> listAll(String orderBy) throws Exception ;
     
     T loadById(Serializable id ) throws Exception ;
     
     void update(final T obj) throws Exception ;
     
     public List<T> findByFieldLike(String field, String expression) throws Exception ;
     
 }
 


Agora uma classe genérica que implementará a nossa interface.

Classe HGenericDao

Code:
 public class HGenericDao<T> implements BaseDao<T> {
     
     protected Class<T> objClass = null;
     protected Session session = null;
     
     public HGenericDao(){
     }
     
     public HGenericDao(Class<T> objKlass) {
         this.setObjectClass(objKlass);
     }
     
     public void setObjectClass(Class<T> objectKlass) {
         this.objClass = objectKlass;
     }
 
     public void setSession(Session session) {
         this.session = session;
     }
     
     public Serializable insert(T obj) throws Exception {
         Serializable idGerado = session.save(obj);
         return idGerado;
     }
     
     public T loadById(Serializable id) throws Exception {
         return (T) session.load(this.objClass, id);
     }
     
     public void delete(final T obj ) throws Exception {
         session.delete(obj);
     }
     
     public void update(final T obj) throws Exception {
         session.update(obj);
     }
     
     public List<T> findByExample(final T example) throws Exception {
         Criteria criteria = session.createCriteria(this.objClass);
         criteria.add(Example.create(example).enableLike(MatchMode.ANYWHERE).ignoreCase());
         final List<T> result = criteria.list();
         return result;
     }
     
     public List<T> findByFieldLike(String fieldOnTable, String expression) throws Exception {
         Criteria c = session.createCriteria(this.objClass).add(
                 Restrictions.like(fieldOnTable , expression , MatchMode.ANYWHERE ).ignoreCase());
         return c.list();
     }
     
     public List<T> listAll(String orderBy) throws Exception {
         Criteria criteria = session.createCriteria(this.objClass);
         criteria.addOrder(Order.asc(orderBy));
         final List<T> result = criteria.list();
         return result;
     }
     
 }
 


De posse dessa interface e dessa classe podemos manipular qualquer
Bean Com os métodos mais utilizados acima.
Vamos agora criar nossos beans de exemplo.

Classe anotada Pais
Code:
 @Entity
 @Table(name = "pais")
 public class Pais implements Serializable {
     
     @Id
     @Column(name = "idPais", nullable = false)
     @GeneratedValue
     private Integer idPais;
     
     @Column(name = "nomePais")
     private String nomePais;
     
     @OneToMany(cascade = CascadeType.ALL, mappedBy = "paisidPais")
     private Collection<Estado> estadoCollection;
 
 // Métodos setters e getters omitidos.
 


Classe anotada Estado
Code:
 @Entity
 @Table(name = "estado")
 public class Estado implements Serializable {
 
     @Id
     @Column(name = "idEstado", nullable = false)
     @GeneratedValue
     private Integer idEstado;
 
     @Column(name = "nomeEstado", nullable = false)
     private String nomeEstado;
 
     @Column(name = "siglaEstado")
     private String siglaEstado;
 
     @OneToMany(cascade = CascadeType.ALL, mappedBy = "estadoidEstado")
     private Collection<Cidade> cidadeCollection;
 
     @JoinColumn(name = "Pais_idPais", referencedColumnName = "idPais")
     @ManyToOne
     private Pais paisidPais;
 
 // Métodos setters e getters omitidos.
 


Ok, agora já poderíamos instanciar o HGenericDao e manupular os
dois beans, porém não é um boa pratica, pois e se quizermos um
método especifico para Estado , teríamos que escreve-lo no HGenericDao.
Então a solução mais indicada é criar um interface para cada Bean
e uma classe concreta para tal.

Interface PaisDao
Code:
 public interface PaisDao extends BaseDao<Pais> {
     
     public List<Pais> findByName(String name) throws Exception ;
     
 }
 


Interface EstadoDao
Code:
 public interface EstadoDao extends BaseDao<Estado> {
     
 }
 


Com esses interface criaremos agora nossas classes concretas
Que Implementara nossa interfaces. Note que as interfaces
Filhas Estendem a interface BaseDao especificando já o tipo
De objeto manipulado.

Classe PaisImpDao
Code:
 public class PaisImpDao extends HGenericDao<Pais> implements PaisDao {
     
     public PaisImpDao() {
         super(Pais.class);
     }
     
     public List<Pais> findByName(String nomePais) throws Exception {
         Criteria c = super.session.createCriteria(super.objClass).add(
                 Restrictions.like("nomePais", nomePais , MatchMode.START ).ignoreCase());
         return c.list();
     }
     
 }
 


Classe EstadoImpDao
Code:
 public class EstadoImpDao extends HGenericDao<Estado> implements EstadoDao {
     
       public EstadoImpDao() {
         super(Estado.class);
     }
     
 }
 


Notem agora que nossa classe especifica estende a classe genérica HGenericDao
Já sendo especificado o tipo de objeto que será manipulado.

E agora, precisamos do hibernate.cfg.xml. aqui vou dar um exemplo:
Code:
 <?xml version='1.0' encoding='utf-8'?>
 <!DOCTYPE hibernate-configuration PUBLIC
 "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
 "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
 
 <hibernate-configuration>
     
     <session-factory>
         
         <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
         <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/jdhcp?autoReconnect=true</property>
         <property name="hibernate.connection.username">root</property>
         <property name="hibernate.connection.password">1048576</property>
         <property name="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
         <!-- configuration pool via c3p0--> 
         <property name="c3p0.acquire_increment">1</property> 
         <property name="c3p0.idle_test_period">100</property> <!-- seconds --> 
         <property name="c3p0.max_size">10</property> 
         <property name="c3p0.max_statements">0</property> 
         <property name="c3p0.min_size">5</property> 
         <property name="c3p0.timeout">100</property> <!-- seconds --> 
         <property name="show_sql">true</property>
         
     </session-factory>
     
 </hibernate-configuration>
 


Tudo certo, agora é só usar o menta para injetar as classes concretas e utilizar nosso Dao.

Agora nosso ApplicationManager.

Code:
 public class ApplicationManager  extends org.mentawai.core.ApplicationManager {
     
     SessionFactory sessionFactory;
     
     private ActionConfig ac;
     
      public ApplicationManager() {
     }
     
     public void init(Context application) {
         
 // VAMOS agora crier nossa sessionFactory para passar
 // para o hibernateFilter.
 
         sessionFactory = new AnnotationConfiguration()
          .addAnnotatedClass(Estado.class)
         .addAnnotatedClass(Pais.class)
         .configure()
         .buildSessionFactory();
         
 //IoC para criar as instancias de nossa classes concretas que
 // será injetada nas nossas actions.
 
         ioc("paisDao", PaisImpDao.class); 
         ioc("estadoDao", EstadoImpDao.class);
          
     }
     
     public void loadActions() {
         
         //   setDebugMode(true);
         
         List<Filter> commons = new ArrayList<Filter>();
 
 // FILTRO IoC que ira instanciar as classes indicadas acima
 // atribuindo as chaves passasdas.
         commons.add(new IoCFilter());
 
 // FILTRO que tentara injetar as instancias criadas pelo IoC
 // dentro de nossas action sem a necessidade de um método set
         commons.add(new InjectionFilter());
 
 // Note que passamos a sessionFactory pronta para nosso HibernateFilter.
         commons.add(new HibernateFilter(true, sessionFactory));
 
 // FILTRO que satisfará qualquer dependencia configurada.
         commons.add(new DIFilter());
 
 // Filtro para validação
         commons.add(new ValidatorFilter());
         addGlobalFilter(commons);
         
 // Nosso DI que injetara uma session para quem precisar.
         di("session", Session.class);
         
 // Aqui simples configurações de exemplo
         ac = action(PaisAction.class)
         .fwdOk("/jsp/localidades/pais.page");
         .fwdError("/jsp/localidades/paisError.page")
         
         action(PaisAction.class, "add")
         .fwdOk("/jsp/localidades/pais.page")
         .on(ERROR, new Chain(ac));
         
         ac = action(EstadoAction.class)
         .fwdOk("/jsp/localidades/estado.page");
         
         action(EstadoAction.class , "add")
         .fwdOk("/jsp/localidades/estado.page")
         .on(ERROR, new Chain(ac));
         
     }
     
     public void loadLists() throws IOException {
     }
     
     public void loadLocales() {
         LocaleManager.add(new Locale("pt", "BR"));
     }
     
 }
 


Tudo pronto. Agora é so usar nossos Daos nas actions criando as
Variáveis de instancias com o mesmo nome da chave atribuída no
IoC.
Exemplo de uma action PaisAction.
Code:
 public class PaisAction extends BaseAction implements Validatable {
 
 // REPARE que usamos a interface PaisDao como tipo de variavel 
 // e o nome paisDao é a chave colocada no IoC no ApplicationManager
 //     ioc("paisDao", PaisImpDao.class)
 // e o InjectionFilter injetará automaticamente.
 
     PaisDao paisDao = null;
     
     private static final String CAMPO_REQUERIDO = "Campo Requerido!";
     private static final String INVALID_LENGHT = "Minimo 3 caracteres";
     
     private List<Pais> list;
     
     public PaisAction() {
     }
 
     public String execute() throws Exception {
         output.setValue("paises", buildListForDisplayTag());
         return SUCCESS;
     }
     
     public String add() throws Exception {
         String nome = input.getStringValue("nomePais");
         Pais pais = new Pais();
         pais.setNomePais(nome);
   
         paisDao.insert(pais);
         return execute();
     }
     
     public List<Pais> buildListForDisplayTag() throws Exception {
         list = paisDao.listAll("nomePais");
         if(list.isEmpty()){
             list.add(new Pais(new Integer(0), "Não há paises cadastrados" ));
         }
         return list;
     }
     
     public void initValidator(Validator val, String innerAction) {
         if(innerAction != null && innerAction.equals("add")) {
             val.add("nomePais", new RequiredFieldRule() , CAMPO_REQUERIDO);
             val.add("nomePais", new StringRule(3), INVALID_LENGHT);
         }
     }
     
 }
 


Exemplo de uma Action EstadoAction
Code:
 public class EstadoAction extends BaseAction implements Validatable {
     PaisDao paisDao = null;
     EstadoDao estadoDao = null;
     
     private static final String CAMPO_REQUERIDO = "Campo Requerido!";
     private static final String INVALID_LENGHT_SIGLA = "Mínimo 2 caracteres";
     private static final String INVALID_LENGHT = "Minimo 3 caracteres";
     /** Creates a new instance of EstadoAction */
     public EstadoAction() {
     }
 
     public String execute() throws Exception {
         Iterator paisList = paisDao.listAll("nomePais").iterator();
         SimpleListData paisesList = new SimpleListData("paises");
         while (paisList.hasNext()) {
             Pais obj = (Pais) paisList.next();
             paisesList.add(obj.getIdPais(),obj.getNomePais());
         }
         output.setValue("paises", paisesList);
         output.setValue("estados", estadoDao.listAll("nomeEstado"));
         return SUCCESS;
     }
     
     public String add() throws Exception{
         String nomeEstado = input.getStringValue("nomeEstado");
         String sigla = input.getStringValue("sigla");
         Integer paisId = input.getIntValue("pais");
         
         Estado estado = new Estado();
         estado.setNomeEstado(nomeEstado);
         estado.setSiglaEstado(sigla);
         estado.setPaisidPais(new Pais(paisId));
        
         estadoDao.insert(estado);
       
         output.setValue("nome", null);
         output.setValue("sigla", null);
         return execute();
     }
 
     public void initValidator(Validator val, String innerAction) {
         if(innerAction != null && innerAction.equals("add")){
             val.add("nomeEstado", new RequiredFieldRule(), CAMPO_REQUERIDO);
             val.add("sigla", new RequiredFieldRule(), CAMPO_REQUERIDO);
             val.add("sigla", new StringRule(2,2) , INVALID_LENGHT_SIGLA);
             val.add("nomeEstado", new StringRule(3) , INVALID_LENGHT);
         }
     }
     
 }
 


Muitos novatos devem estar se perguntando:
Para que criar interfaces e classes concretas que não contem nada?

È simples digamos que eu queira criar um novo método
Específico para a Dao EstadoDao, sem as nossas interfaces
E classes separadas, teríamos que criar na nossa HGenericDao, mas
Sem necessidad pois é um método que diz respeito apenas para Estado,
Então, criaremos tal método na classe EstadoImpDao e assinaremos o
Método na interface EstadoDao e pronto, teremos disponível em nossa
Actions o nosso novo método.

Bom é isso pessoal.

Robert Gil
Coordenador de Desenvolvimento / Administrador de Redes.

Twitter
[Email] [MSN]
IceW0lf


[Avatar]

Joined: 16/03/2006 08:33:38
Messages: 1546
Location: Brasília
Offline

Parabéns pela iniciativa Robert

Leiber Wallace
Voixy ::: Soluções em Telecomunicações
saoj



Joined: 01/07/2005 09:59:17
Messages: 2846
Location: Rio de Janeiro, RJ
Offline


Valeu! Depois quando sobrar um tempo colocamos no FAQ do menta!

Parabéns! Ficou bem legal!

Sergio Oliveira

robertwgil


[Avatar]
Joined: 23/02/2007 17:22:13
Messages: 745
Location: São Paulo - SP - Brasil
Offline

Lembrando que esses codigos sao apenas para ilustrar o anunciado do
topico..

agora respondendo a pergunta..

é uma session do hibernate sim

e retorno um Serializable porque no hibernate
quando voce usa o insert para gravar no banco, ele
retorna a id gerado, hj em dia usam-se mais o persist,
ou o saveOrUpdate, porem ambos não voltam o id que
foi gerado.

e outra coisa. na interface nem seria necessario ter esse
metodo setSession() , pois o menta injeta as session via
DI, direto nas actions, tirando esse metodo setSession sua
interface fica dasacoplada de qualquer tipo de persistencia de
dados, voce poderia pro exemplo passar uma session no
MentaBean, JDBC etc...

Robert Gil
Coordenador de Desenvolvimento / Administrador de Redes.

Twitter
[Email] [MSN]
MentaBeginer



Joined: 15/09/2007 19:39:35
Messages: 1
Offline

Olá a todos.

Post muito interessante, está me ajudando muito. Mas, gostaria de solicitar auxilio a vocês.

Construi uma aplicação seguindo o exemplo (apenas utilizei templates para construir as páginas, o que está funcionando corretamente). Porém, quando faço qualquer acesso à base de dados, caio na seguinte exceção:

Code:
com.sun.jdi.InvocationException occurred invoking method


Não aparece no console nem nada, só vejo quando estou debugando, e tento ver o conteúdo da variável. Tentei ver no google o que causa o problema, mas, não fui bem sucedido (não entendi muito bem o que gera essa exceção).

Alguém já passou por esse mesmo problema? Utilizo Eclipse Europa, e normalmente o WTP para construir projetos dinâmicos. Nesse projeto, estou utilizando o Jboss 4.0.2.

Obrigado.
edurezende



Joined: 07/01/2008 07:39:02
Messages: 11
Offline

robertwgil e se eu tenho a service(Não quero lidar com DAOS nas Actions) como seria o meu ApplicationManager
IceW0lf


[Avatar]

Joined: 16/03/2006 08:33:38
Messages: 1546
Location: Brasília
Offline

Basta vc criar os IoC e DIs necessários no seu AplicationManager.

Exemplo:

ioc("pessoaDAO", pessoaDAO);
ioc("pessoaService", PessoaServiceImpl.class);

di("pesosaDAO", pessoaDAOImpl.class);

E na sua action chamar seu service.

ActionQualquer
private PessoaService pessoaService;

Pessoa pessoa = pessoaService.getAll();

Etc. etc. e etc.

Qualquer coisa tamos ai.

Tem segredo isso no menta nao.

Leiber Wallace
Voixy ::: Soluções em Telecomunicações
 
Forum Index -> F.A.Q.
Go to:   
Powered by JForum 2.1.6 © JForum Team