Olá pessoal.
Estou com um dúvida sobre a melhor maneira de atualizar um objeto que possui vários outros objetos e também apontam para outros objetos. Vou tentar ilustrar:
Tenho a seguinte hierarquia:
Funcionario -> Pessoa -> Endereço -> Logradouro
Na minha aplicação preciso atualizar o logradouro do endereço de um funcionário, pois bem, acessei o crud de funcionario e alterei a valor de logradouro.
No momento de fazer a atualização no banco é que me veio a dúvida. Para realizar essa atualização preciso abrir um transação (EntityManger.begin) e, dentro dela (transação), efetuar as modificações no objeto para depois efetuar o commit e, por fim, fechar a entityManger.
Para atualizar logradouro teria que sair atualizando todas as entidades que estão no meio do caminho ou poderia simplesmente fazer:
funcionario.getPessoa().getEndereco().setLogradouro(logradouro);
?
Lembrando que logradouro também é um objeto.
já tentei isso e não deu certo. Para atualizar teria que primeira atualizar o logradouro com o novo elemento, depois o endereço, depois a pessoa e, finalmente, o funcionário. Em uma aplicação com muitos relacionamentos do tipo fica meio confuso e muito fácil de cometer erros. Qual seria uma solução mais organizada para isso?
Obrigado.
[quote=Hebert Coelho]Qual erro que deu?
[/quote]
Na verdade, não deu nenhum erro, mas quero tentar uma forma melhor de fazer isso.
Por exemplo. No projeto que desenvolvendo desenvolvi o seguinte DAO:
package br.flexweb.dao;
import java.io.Serializable;
import java.util.List;
import javax.persistence.EntityManager;
import br.flexweb.JPAUtils.JPAUtil;
import br.flexweb.models.Funcionario;
import br.flexweb.models.TipoLogradouro;
public class DAO<T> implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private final Class<T> classe;
public DAO(Class<T> classe){
this.classe = classe;
}
public T buscar(Integer id){
EntityManager em = new JPAUtil().getEntityManager();
em.getTransaction().begin();
T objeto = em.getReference(classe, id);
em.close();
return objeto;
}
@SuppressWarnings("unchecked")
public List<T> listar(){
List<T> objetos;
EntityManager em = new JPAUtil().getEntityManager();
objetos = em.createQuery("select e from " + classe.getName() + " e").getResultList();
em.close();
return objetos;
}
@SuppressWarnings("unchecked")
public List<TipoLogradouro> completar(String s, String coluna){
List<TipoLogradouro> objetos;
EntityManager em = new JPAUtil().getEntityManager();
//System.out.println("select e from TipoLogradouro e where descricao like '" + s + "'");
objetos = em.createQuery("select e from " + classe.getName() + " e where "+ coluna + " like '%" + s + "%'").getResultList();
em.close();
return objetos;
}
public void adicionar(T objeto){
EntityManager em = new JPAUtil().getEntityManager();
em.getTransaction().begin();
em.persist(objeto);
em.getTransaction().commit();
em.close();
}
public void atualizar(T objeto){
System.out.println(((Funcionario)objeto).getPessoa().getEndereco().getTipoLogradouro().getId() + " ---- DAO");
EntityManager em = new JPAUtil().getEntityManager();
em.getTransaction().begin();
em.merge(objeto);
em.getTransaction().commit();
em.close();
}
public void remover(T objeto){
EntityManager em = new JPAUtil().getEntityManager();
em.getTransaction().begin();
objeto = em.merge(objeto);
em.remove(objeto);
em.getTransaction().commit();
em.close();
}
}
O meu método atualizar não funciona, não comita as alterações que faço no meu objeto. Para conseguir fazer isso tive que criar um método fora deste dao, por exemplo, dentro de FuncionarioDAO para conseguir atualizá-lo. Queria deixar tudo dentro do DAO para ficar mais organizado e a implementação ser mais limpa.
Nunca usei JPA puro, mas pelo pouco que vi do seu código percebi que o Hibernate é muito mais prático.
Para qualquer um dos métodos da sua DAO dá fazer com 1-4 linhas de código usando o Hibernate e named queries. Talvez seja interessante você tentar migrar, não deve levar muito tempo.
Tenho pouca experiência com o Hibernate, mas até o momento achei que aumentou demais a minha produtividade.
Estou no estágio agora, mas, se quiser, posto uma DAO minha pra você ver a simplicidade do código.
[quote=fernandotnl]Nunca usei JPA puro, mas pelo pouco que vi do seu código percebi que o Hibernate é muito mais prático.
Para qualquer um dos métodos da sua DAO dá fazer com 1-4 linhas de código usando o Hibernate e named queries. Talvez seja interessante você tentar migrar, não deve levar muito tempo.
Tenho pouca experiência com o Hibernate, mas até o momento achei que aumentou demais a minha produtividade.
Estou no estágio agora, mas, se quiser, posto uma DAO minha pra você ver a simplicidade do código.[/quote]
Então coloca o seu DAO para eu dar uma analisada.
Vlw
[quote=fernandotnl]Nunca usei JPA puro, mas pelo pouco que vi do seu código percebi que o Hibernate é muito mais prático.
Para qualquer um dos métodos da sua DAO dá fazer com 1-4 linhas de código usando o Hibernate e named queries. Talvez seja interessante você tentar migrar, não deve levar muito tempo.
Tenho pouca experiência com o Hibernate, mas até o momento achei que aumentou demais a minha produtividade.
Estou no estágio agora, mas, se quiser, posto uma DAO minha pra você ver a simplicidade do código.[/quote]E pq não com JPA também? O.o
[quote=ThEDiegO][quote=Hebert Coelho]Qual erro que deu?
[/quote]
Na verdade, não deu nenhum erro, mas quero tentar uma forma melhor de fazer isso.[/quote]Eu não vejo como fazer isso de modo diferente.
Você realmente deve navegar no objeto.
ou então você busca o endereço pelo id e altera apenas ele. Um modo otimizado de fazer isso é utilizando o getReference do JPA: JPA Consultas e Dicas.
Não existe uma opção de atualizar em cascata?
[quote=Hebert Coelho][quote=fernandotnl]Nunca usei JPA puro, mas pelo pouco que vi do seu código percebi que o Hibernate é muito mais prático.
Para qualquer um dos métodos da sua DAO dá fazer com 1-4 linhas de código usando o Hibernate e named queries. Talvez seja interessante você tentar migrar, não deve levar muito tempo.
Tenho pouca experiência com o Hibernate, mas até o momento achei que aumentou demais a minha produtividade.
Estou no estágio agora, mas, se quiser, posto uma DAO minha pra você ver a simplicidade do código.[/quote]E pq não com JPA também? O.o[/quote]
Como disse, nunca usei JPA Puro. Por isso, não conheço as definições específicas dessa forma de persistência de dados. Mas observando a DAO do ThEDiegO vi que a forma que aprendi no Hibernate é mais simples.
Além disso, fiz uma pesquisa sobre as vagas disponíveis no mercado para alguns frameworks Java e descobri que o Hibernate é o mais procurado 
[quote=fernandotnl][quote=Hebert Coelho][quote=fernandotnl]Nunca usei JPA puro, mas pelo pouco que vi do seu código percebi que o Hibernate é muito mais prático.
Para qualquer um dos métodos da sua DAO dá fazer com 1-4 linhas de código usando o Hibernate e named queries. Talvez seja interessante você tentar migrar, não deve levar muito tempo.
Tenho pouca experiência com o Hibernate, mas até o momento achei que aumentou demais a minha produtividade.
Estou no estágio agora, mas, se quiser, posto uma DAO minha pra você ver a simplicidade do código.[/quote]E pq não com JPA também? O.o[/quote]
Como disse, nunca usei JPA Puro. Por isso, não conheço as definições específicas dessa forma de persistência de dados. Mas observando a DAO do ThEDiegO vi que a forma que aprendi no Hibernate é mais simples.
Além disso, fiz uma pesquisa sobre as vagas disponíveis no mercado para alguns frameworks Java e descobri que o Hibernate é o mais procurado
[/quote]Engraçado, nunca estudei Hibernate, apenas JPA e nunca me faltou empregou ou alguma pergunta que não consegui resolver.
Caso você queira aprender um pouco mais, aqui explica o que é o JPA e o que é o Hibernate: JPA: Mini Livro - Primeiros passos e conceitos detalhados.
Já criei projeto que utilizasse Hibernate, EclipseLink e OpenJPA tudo apenas conhecendo JPA.
No link JPA: Mini Livro - Primeiros passos e conceitos detalhados mostra como funciona o “Cascade” do JPA/Hibernate.
Hebert Vou dar uma olhada.
ThEDiegO , conforme tinha prometido, segue abaixo uma versão simplificada de uma DAO utilizando Hibernate:
public class PessoaDAOImpl implements PessoaDAO {
@Override
public void criaPessoa(Pessoa pessoa) throws DAOException {
HibernateUtil.getSessionFactory().saveOrUpdate(pessoa);
}
@Override
public Pessoa buscaPessoa(Long id) throws DAOException {
Query query = HibernateUtil.getSessionFactory().getNamedQuery("Pessoa.findPessoaById");
query.setParameter("id",id);
List<Pessoa> list = query.list();
return (Pessoa) list.get(0);
}
@Override
public List<Pessoa> listaPessoas() throws DAOException {
Query query = HibernateUtil.getSessionFactory().getNamedQuery("Pessoa.findAll");
List<Pessoa> list = query.list();
return list;
}
@Override
public void modificaPessoa(Pessoa pessoa) throws DAOException {
HibernateUtil.getSessionFactory().update(pessoa);
}
@Override
public void deletaPessoa(Pessoa pessoa) throws DAOException {
HibernateUtil.getSessionFactory().delete(pessoa);
}
public Session getSessionFactory() {
return HibernateUtil.getSessionFactory();
}
}
O método getSessionFactory() retorna sessionFactory.openSession(). Faço a instanciação da sessionFactory através do Spring, junto com as declarações de propriedades do hibernate(classes anotadas).
Vi outras formas de fazer isso, mas gostei bastante dessa abordagem e, até o momento tem sido, bem útil.
Espero ter ajudado. 