JPA com Hibernate + JSF + MySQL

olá Pessoal,

Neste post, vou mostrar como usar JPA para seus projetos JEE tendo como provider o nosso Hibernate e para o view usaremos JSF. Alguns adoram o TopLink da Oracle, eu tive serios problemas com ele na parte de config, e cansei de me stressar com coisas operacionais e mantenho meu querido Hibernate como provider.

Aplicação será bem simples, apenas cadastrar um cliente. Limitamos os dados do form, pois o objetivo é mostrar como criar um ambiente para development tendo JPA nos seus projetos. Já mostrei em outros posts, como criar um projeto JPA para Java Básico. Então, recebi alguns emails e para JEE?

Lets go…

Oportunidade Java:

Estamos disponibilizando uma vaga para desenvolvedor Senior Web
. Carga horária será de 8 horas diárias. Os requisitos técnicos para esta contratação são:

- Conhecimentos nas APIs: JSF, Hibernate;
- Conhecimentos nos patterns MVC, DAO, VO;
- Desejável conhecimento em RichFaces

Regime De trabalho é CLT. O salário será de 4.000 mais benefícios. 

Interessados enviar currículos para atendimento@leiria.com.br

Obrigado.

Posts relacionados

Requisitos

Iniciando

Na imagem a seguir você tem toda a estrutura do projeto, observe que já criei as bibliotecas para o projeto e estas foram adicionadas. Se não quiser adicioanr as bibliotecas ao projeto, copie os .jars para a pasta lib e pronto. Lembre-se que ao adicionar uma biblioteca ao projeto, o stupid Eclipse não copia os .jars para a pasta lib. (ao contrário do netbeans 🙂 ).

Não esqueça também de criar um schema e uma table no MySQL, aqui chamaremos de sistemas e clientes respectivamente.

estrutura

1.monte uma estrutura conforme a imagem acima.

Para os arquivos em .jsp e .xml tive que colocar no formato imagem. Infelizmente o plugin para code no wordpress, esse é estressante quando envolve xml, html etc. preciso ficar dando um espaco para cada par de < > senão ele bagunça todo código ou até converte para qualquer outra coisa. Já gastei 1 hora somente para tentar configurar isso. Em função disso, coloquei no formato img o code bem organizado. O lado bom, é que você poderá praticar sem dar ctrl + c e ctrl + v. 🙂

E como sempre boa parte das explanações estão dentro do code no formato de comentário, lado-lado para facilar a compreensão.

Desenvolvimento

2.primeiro passo é criar o bean e fazer as devidas anotações, então veja abaixo o nosso cliente bean como está:

package br.com.bean;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name="cliente")//caso o nome da tabela seja diferente informe aqui
public class Cliente {
	@Column(name="nome")
	private String nome;

	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	//anotação acima indica que o campo será gerado automaticamente pelo BD
	@Column(name="id")
	private int id;
	@Column(name="sobrenome")
	private String sobrenome;
	@Column(name="cidade")
	private String cidade; 

	public Cliente() {
		// TODO Auto-generated constructor stub
	}

	public String getNome() {
		return nome;
	}

	public void setNome(String nome) {
		this.nome = nome;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getSobrenome() {
		return sobrenome;
	}

	public void setSobrenome(String sobrenome) {
		this.sobrenome = sobrenome;
	}

	public String getCidade() {
		return cidade;
	}

	public void setCidade(String cidade) {
		this.cidade = cidade;
	}

}

Agora vamos partir para criar o nosso DAO, que nele teremos a nossa fábrica de conexão. E poderiamos ter métodos genéricos como salvar, deletar, atualizar etc.Mas, não vamos implementar todos.

package br.com.dao;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

public class DAO {

	private EntityManagerFactory emf; 

	/* se vc já está acostumado com Hibernate
	 * a ideia é a mesma do método de fabrica que
	 * criamos para os Session que vem do SessionFactory
	 * Aqui temos apenas nomeclatura diferente, pense assim.
	 */
	public EntityManager getEntityManager(){

		//responsavel pela persistencia
		return emf.createEntityManager();
	}
	public DAO() {
		//chamo ele de reprodutor da instância
		emf = Persistence.createEntityManagerFactory("sistemas");

		/* o nome passado vem do arquivo persistence.xml que contém as configs
		 * para conexão com o BD.
		 */
	}}

Agora vamos criar a classe que vai fazer a persistencia com os dados do cliente. É a ClienteDAO.java esta classe extends a classe DAO, para conseguirmos pegar um objeto objeto EntityManager que é responsável pelas inclusões, exclusões e atualizações.

package br.com.dao;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.Query;

import br.com.bean.Cliente;

public class ClienteDAO extends DAO {

	public void salvar(Cliente cliente){
		//obtendo o EntityManager
		EntityManager em = getEntityManager();
		try{
			//inicia o processo de transacao
			em.getTransaction().begin();
			//faz a persistencia
			em.persist(cliente);
			//manda bala para o BD
			em.getTransaction().commit();
		}catch (Exception e) {
			//se der algo de errado vem parar aqui, onde eh cancelado
			em.getTransaction().rollback();
		}
	}

	public List exibir(){
		EntityManager em = getEntityManager();
		try{
			Query q = em.createQuery("select object(c) from Cliente as c");

		return q.getResultList();}
		finally{
			em.close();
		}
	}
}

Agora criaremos a classe ClienteController quer terá a responsabilidade de direcionar a comunicação do JSF e pegar o foi digitado no form e persistir.

package br.com.controller;
import javax.faces.model.DataModel;
import javax.faces.model.ListDataModel;
import br.com.bean.Cliente;
import br.com.dao.ClienteDAO;
public class ClienteController {
	private Cliente cliente;
	private DataModel model;
	public ClienteController() {
		cliente = new Cliente();
	}

	public Cliente getCliente() {
		return cliente;
	}
	public void setCliente(Cliente cliente) {
		this.cliente = cliente;
	}

	public String salvar(){
		ClienteDAO clientedao = new ClienteDAO();
			clientedao.salvar(cliente);
		return "salvar";
	}
	public DataModel getTodos(){
			ClienteDAO clientedao = new ClienteDAO();
			model = new ListDataModel(clientedao.exibir());
		return model;
	}
}

Vamos configurar o no velho e querido face-config.xml

faceconfigdesign

Criando arquivo persistence.xml

o arquivo que vamos precisar para conectar ao banco de dados, parecido como hibernate.cfg.xml, em respeito de ter a mesma função, conectar ao BD.

Observe o name da persistence-unit pois, eh ele que usamos no nosso DAO.java

persistence

Não esqueça que terá que criar um folder META-INF em JavaSource e colocar o persistence.xml neste folder e não coloca-lo dentro do META-INF de WebContent. Alguns programadores acabam confundido e dai recebe as velhas exceções e ficam stressado. Take care easy!

Criando as pages JSF

1.Agora criamos três páginas .jsp com JSF, uma será index que redireciona para cadastro.jsf e a outra é somente uma mensagem dizendo que foi cadastrado com sucesso.

Index.jsp

Coloque o código abaixo na página index.jsp

cadastrojsf

Testando

Mande executar seu projeto. Clique nele e vá em Run ==> Run as ==> Run on Server

  • Cadastre um cliente

E depois verifique se ele está realmente no BD. Veja abaixo meus prints:

testecad

testesucessocad

testemysqlcad

Pessoal, vou ficando por aqui, espero que tenham gostado do post, o objetivo era dar o “ABC Prático” de JPA com JEE usando o framework JSF.

Abracos, see you later.! 🙂

Open Session View – Hibernate Solução

solutionproblem

olá Pessoal,

No post de hoje vou falar de um problema que todos que estão trabalhando com Hibernate não está livre de se deparar com ele. É o velho LazyInitializationException que acontece e deixa o pobre do desenvolvedor stressado.

Neste post pretendo ser menos teórico e mais prático, pois tem muita coisa na net explicando o porque temos o LazyInitializationException, porém poucos explicaram de forma prática a solução. O mais próximo foi este site. Que se você reparar direito tem um pequeno erro no mapeamento do filtro.

Então aqui vou mostrar como resolver o problema, pois também fui afetado com este problema e levei umas quase 3 horas para resolver. E agora vejo que era algo simples, mas eu precisava entender o por que?! de cada exceção que vinha recebendo. Para este este post usei o post que está no Jboss Community, porém fiz algumas adaptações.

Lets go…

Vou usar a técnica de reutilização da informação então o Paulo da Caelum já fez uma abordagem excelente do porque desse problema , veja.

Desenvolvendo

Se você não quer desenvolver os codes a seguir, então mude o relacionamento para EAGER ao invés de usar o LAZY. Os codes a seguir é útil para quem necessita de ser LAZY o relacionamento.

  1. crie um novo package no seu projeto o meu chamei de : br.com.filtro

O pessoal do Jboss Community não colocou quais classes deveriamos importar, um programador inexperiente pode se atrapalhar e importar classes inapropriadas. Em função disso coloquei abaixo o código completo.

  1. Crie a classe HibernateSessionRequestFilter conforme abaixo: (fique atento ao meu comentário na classe)

    package br.com.filtro;
    
    import java.io.IOException;
    
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.hibernate.SessionFactory;
    import org.hibernate.StaleObjectStateException;
    
    import br.com.dao.DAO;
    
    public class HibernateSessionRequestFilter implements Filter {
    
    	 private static Log log = LogFactory.getLog(HibernateSessionRequestFilter.class);
    
    	    private SessionFactory sf;
    
    	    public void doFilter(ServletRequest request,
    	                         ServletResponse response,
    	                         FilterChain chain)
    	            throws IOException, ServletException {
    
    	        try {
    	          System.out.println("iniciando a transacao com o DB");
    	            sf.getCurrentSession().beginTransaction();
    
    	            // Call the next filter (continue request processing)
    	            chain.doFilter(request, response);
    
    	            // Commit and cleanup
    	            log.debug("Committing the database transaction");
    	          sf.getCurrentSession().getTransaction().commit();
    
    	        } catch (StaleObjectStateException staleEx) {
    	            log.error("This interceptor does not implement optimistic concurrency control!");
    	            log.error("Your application will not work until you add compensation actions!");
    	            // Rollback, close everything, possibly compensate for any permanent changes
    	            // during the conversation, and finally restart business conversation. Maybe
    	            // give the user of the application a chance to merge some of his work with
    	            // fresh data... what you do here depends on your applications design.
    	            throw staleEx;
    	        } catch (Throwable ex) {
    	            // Rollback only
    	            ex.printStackTrace();
    	            try {
    	                if (sf.getCurrentSession().getTransaction().isActive()) {
    	                    log.debug("Trying to rollback database transaction after exception");
    	                    sf.getCurrentSession().getTransaction().rollback();
    	                }
    	            } catch (Throwable rbEx) {
    	                log.error("Could not rollback transaction after exception!", rbEx);
    	            }
    
    	            // Let others handle it... maybe another interceptor for exceptions?
    	            throw new ServletException(ex);
    	        }
    	    }
    
    	    public void init(FilterConfig filterConfig) throws ServletException {
    	        //log.debug("Initializing filter...");
    	       // log.debug("Obtaining SessionFactory from static HibernateUtil singleton");
    	        sf = DAO.getSessionFactory();//vem da minha classe DAO
    	    }
    
    	    public void destroy() {}
    
    }
  2. Agora veja como está meu DAO:

    package br.com.dao;
    
    import org.hibernate.Session;
    import org.hibernate.SessionFactory;
    import org.hibernate.cfg.Configuration;
    
    public class DAO {
    	private static ThreadLocal threadlocal = new ThreadLocal();
    	private static SessionFactory sessionFactory = new Configuration().configure().
    	buildSessionFactory(); 
    
    public DAO() {
    	// TODO Auto-generated constructor stub
    }
    public static  Session getSession(){
    	Session session = (Session) threadlocal.get();
    	if(session == null){
    		session = sessionFactory.openSession();
    		threadlocal.set(session);
    	}
    	return session;
    }
    	public void begin(){
    		getSession().beginTransaction();
    
    	}
    public void commit(){
    	getSession().getTransaction().commit();
    }
    
    public void rollback(){
    	getSession().getTransaction().rollback();
    }
    public void close(){
    	getSession().close();
    }
    public static void shutdown() {
    	// Close caches and connection pools
    	getSessionFactory().close();
    	}
    //passamos ele para o Filter
    public static SessionFactory getSessionFactory() {
    	return sessionFactory;
    }
    public static void setSessionFactory(SessionFactory sessionFactory) {
    	DAO.sessionFactory = sessionFactory;
    }
    
    }

Não precisei alterar nada da configuração padrão do hibernate.

  1. Abra seu arquivo hibernate.cfg.xml e adicione a linha abaixo:

    < property name=”hibernate.current_session_context_class”>thread  < /property>

  2. Salve e execute sua aplicação, veja se os println do Filter serão impressos (claro, os que estão nos catches nem devem aparecer). Em caso positivo está tudo ok.

  3. Agora teste várias vezes sua app e veja se verá o problema com LazyInitializationException. Aqui ele sumiu de vez, graças à deus.

A única coisa que mudei na classe HibernateSessionRequestFilter, foi informar meu SessionFactory e o resto o Filter fez o trabalho dele.

Bom vou ficando por aqui, espero que tenham gostado do post. Não posso deixar de agradecer ao autor Edson Gonçalves que contribuiu bastante para este post, desde a indicação do link, como as explanações pelo mesmo que foi contribuindo  até encontrar a solução, o colega Rafael Viana (GUJ) já tinha passado por um problema parecido e compartilhou sua experiência opinando como poderia ser resolvido.

Fica ai agora a versão em português do problema. Abracos, see you next post.

Solucionando Communication link failure Hibernate com Pool + Mysql

olá Pessoal,

Hoje vou apresentar como resolver o problema abaixo quando temos nossa aplicação em produção e onde apostaríamos tudo que estava ok, pois em teste vc nunca tinha visto à exceção a seguir. Mas, pq em produção ela aparece e o cliente liga dizendo que está dando erro?

Bem, eu sofri muito com essa exceção, pesquisei bastante e vi várias dicas porém nenhuma delas eu conseguia resolver, dai conversando com Edson Gonçalves o mesmo me passou dois links importantes o qual encontrei a solução um está em inglês e outro é da Caelum explicando o outro problema que é broken pipe que é bem comum aparecer.

Lets go..

Posts Relacionado:

Mas, Por que temos essa exceção em PRODUÇÃO?

hibernateexcecaopool

A resposta é bem simples, se a conexão com seu banco ficar inativo por mais de 8 horas no caso do MySql, então o banco mata a conexão. E quando o cliente usando o pool de conexão tenta usar, já eh tarde demais.

Solucionando

Aqui estou usando o pool de conexão que é required em qualquer aplicação JEE, até por questão de manutenção, porém vou limitar o code apenas para meu arquivo context.xml.

Portanto abra seu arquivo META-INF/context.xml que faz o pool de conexão que você deve deixa-lo como o código a seguir:


  

 


Depois disso, manda o xml para produção, dar um restart no servidor e testa. Aqui resolveu. Até que fim.

o código anterior era assim:


  

 

Bem, espero que o post tenha ajudado, resolvi fazer esse post tendo como referencia o post em ingles, devido durante as minhas pesquisas não achei nada em português tão objetivo e direto para resolver o problema, só encontrava, discussões e opiniões de como poderia ser resolvido, mas nada de resolver. Agora já temos :). Mas, não se esqueça que isso tem efeitos apenas em produção.

abraços, see ya!!

Hibernate com Pool de Conexão

Olá Pessoal,

Hoje o post é bem simples, na verdade considero este como uma continuação do post sobre pool de conexão. Vou mostrar aqui como fazer hibernate usar o pool de conexão através de uma JNDI. Então será um post bem pequeno, já que vou adicionar apenas as informações referente ao arquivo hibernate.cfg.xml. Se quer comecar do zero, veja o post anterior.

Lets go…

Configurando

  1. Certifique-se que você tem no seu projeto o arquivo context.xml e web.xml configurado corretamente.

  2. Tanto faz se seu projeto é JSF Project ou Dynamic Web Project desde que seja para plataforma JEE.

  3. Não esqueça de adicionar os .jars do hibernate ao seu projeto, se tem dúvida veja neste post.

  4. Agora vamos para a parte mais simples, configurar o arquivo hibernate.cfg.xml. Então deixe seu arquivo conforme abaixo:




java:/comp/env/jdbc/blog
thread
org.hibernate.transaction.JDBCTransactionFactory
org.hibernate.dialect.MySQL5InnoDBDialect
0



 

Pronto observe que agora seu arquivo de configuração do hibernate ele “aponta” para o JNDI que criamos, e quando o schema ou caminho do BD mudar, vamos apenas alterar lá no JNDI e o hibernate já pega a nova informação. Simples não?

Abracos, espero que tenham gostado do post.

org.hibernate.Session Hibernate Solução Eclipse

olá Pessoal,

Hoje vou apresentar um pequeno probleminha que alguns já passaram usando o hibernate. Porém, o problema não é do framework e sim do Eclipse que não importa os .jars quando este é adicionado usando library da própria IDE. A situação é bem simples: “o programador está convicto que tudo está OK, nao falta nenhum .jars, os imports correto etc.” Mas, ao executar aplicação e tentar salvar algo no BD, recebe uma exceção org.hibernate.Session.

Neste post vou mostrar aonde está o problema.

Lets go…

O problema

Como relatei o problema é na IDE Eclipse que ela nao faz os imports dos .jars que você adicionou ao projeto usando library. Que na verdade os .jars deveriam está na pasta lib do seu projeto fisicamente. Porém não é isso que acontece. Experimente ir na pasta lib do seu projeto e veja se vai ver algum .jar do hibernate. Acredito que não e por isso temos essa exceção em um caso como esse.

Abaixo olha os testes que e fiz e como solucionei (acredito que você já sabe como é):

Criei um projeto simples, que cadastra um cargo no BD. Somente para mostrar o problema.

  1. Vamos felizes da vida tentar cadastrar uma novo cargo

  2. Olha que beleza:

  3. Vamos ver o que temos na pasta lib do meu projeto:

  4. Bem,  Não vejo meus arquivos .jars do hibernate que adicionei ao projeto. Onde estão sr. Eclipse? Esse é o problema do Eclipse, nos adicionamos os ,jars e ele nao copia fisicamente os .jars para a pasta lib. Isso dar certo quando é projeto não é  JEE. Como falei neste post.

  5. A solução, é copiar os .jars veja:

  6. Agora vamos testar app novamente

  7. Verificando no meu BD ver:

Pronto, resolvido o problema! Bem, Nem sempre a exceção com hibernate.session está relacionada com a falta dos .jars, as vezes é erro de programação mesmo. Mas, quando você está certo dos seus codes e está usando o Eclipse, não esqueça de ir a pasta lib do projeto e verificar se os .jars do Hibernate realmente estao no seu projeto.

Vou ficando por aqui, espero que a dica tenha ajudado quem está passando por essa situação, eu ja mandei uma nota para equipe do Eclipse, mas eles disseram que isso não é um bug da IDE. Bem, o NetBeans não  tem isso, todas as libraries adicionadas ao projetos, temos os .jars fisicamente no projeto. Então, será que não é uma falha do nosso querido Eclipse? Eu ja reclamo disso desde da versão antes Galileo.

Abracos, see you next post.