segunda-feira, 29 de agosto de 2011

Instanciando um Bean em uma consulta HQL

Em uma consulta HQL quanto projetamos mais que um objeto, o mais comum é acessarmos a consulta por um List<Object[]> essa abordagem não é muito interessante, pois torna nossa consulta muito passível de dar erro, pois basta mudar a ordem das colunas e vamos causar um erro onde a consulta estiver sendo usada.


String hql = "select o.numeroProcesso, o.dataInicio from Processo o";
Query query = EntityUtil.createQuery(hql);
List<Object[]> list = query.getResultList();

Uma abordagem mais interessante é devolver essa consulta como um List<Map<String, Object>> criando os alias paras as colunas projetadas. Dessa maneira uma mudança de ordem na consulta não traria erro para quem a utilizasse:

String hql = "select new map(o.numeroProcesso as numeroProcesso, o.dataInicio as dataInicio) from Processo o";
Query query = EntityUtil.createQuery(hql);
List<Map<String, Object>> list = query.getResultList();
for (Map<String, Object> map : list) {
Object numeroProcesso = map.get("numeroProcesso");
}

A utilização do List<Map<String, Object>> é um avanço, mas pode induzir a erros de runtime, pois o cast fica sobre responsabilidade de quem for utilizar a lista.

Uma maneira mais segura é utilizar o recurso de instanciação do bean via construtor. O hibernate permite que instanciemos em nossa consulta uma classe que as colunas projetadas sejam passadas como parâmetro do construtor da classe:





Com essa abordagem, tornamos nossa consulta bem mais segura, pois vamos devolver uma lista com o nosso bean.



terça-feira, 19 de julho de 2011

Diferenças entre compilador do Eclipse e o da Sun

Aqui na INFOX utilizamos o Eclipse como IDE Java e gosto muito dele. Acho o Eclipse imbatível para escrita de código e só utilizo o Netbeans quando preciso criar alguma tela Swing ;p

Uma das grandes vantagens do Eclipse é seu compilador que é bastante rápido e muito bem integrado a ferramenta. O compilador do Eclipse possui outras vantagens, mas vou deixar este assunto apar outro post e vou focar aqui nas diferenças e nos problemas que elas podem trazer.

Nosso deploy é feito nos servidores por meio de um script que baixa do SVN o projeto, faz algumas mudanças em arquivos de configuração e compila as classes utilizando o JDK da Sun.

Algumas vezes ocorreram problemas de compilação na hora do deploy em classes que compilavam corretamente na IDE com o compilador do Eclipse.

Tomando certo cuidado na hora de desenvolver é possível evitar essas problemas pois eles ocorrem em poucas situações e aqui vou mostrar 3 situações

Segue abaixo imagens com código fonte no Eclipse e no Netbeans :

[1] e [2] Comportamento correto nos dois compiladores, não é possível dar cast de um Object para um boolean (Tipo primitivo) mas sim para um Boolean(Objeto)

[3] Aqui há diferença e onde um dia desses ocorreu um problema, o cast está sendo feito pelo método genérico e o compilador do Eclipse permite que este método faça um cast de Object para boolean, coisa que o da Sun não permite.


[4] Neste caso o eclipse não esta acusando erro ao utilizar a constante privada NAME na anotação @Name e compila normal caso que não ocorre com o compilador da Sun.


[5] Esse é o caso mais gritante onde o compilador do eclipse deveria acusar erro, mas relaxa e compila sem problemas. Dentro de anotações nos parâmetros que recebem vetores o compilador permite esta virgula no final.

Para não dizer que o problema é sempre do compilador do Eclipse, eu já vi um caso de ocorrer um problema que parecia ser um bug no compilador da Sun. Pelo que eu lembre foi algo bem parecido com isto aqui: http://stackoverflow.com/questions/314572/bug-in-eclipse-compiler-or-in-javac

Caso eu encontre outras diferenças/problemas vou continuar a alimentar este post aqui :D

[]'s

terça-feira, 31 de maio de 2011

Problema com equals em entidades usando Hibernate

Há uns meses atrás eu tive um problema com uma combo e motivo do problema era a falta de um equals na classe. As vezes quando a página era renderizada o objeto que estava selecionado era de uma instancia diferente do correspondente da lista e com isso dava inconsistência.

Por este motivo todas as classes precisam do equals e hashcode implementado e o eclipse gera eles automaticamente. Mas ontem eu tive um problema com este equals gerado de maneira automática, pois ele gera o equals dessa maneira:


@Override
 public boolean equals(Object obj) {
  if (this == obj)
   return true;
  if (obj == null)
   return false;
  if (getClass() != obj.getClass())
   return false;
  UsuarioLogin other = (UsuarioLogin) obj;
  if (idUsuario != other.idUsuario)
   return false;
  return true;
 }


Este equals pode gerar dois problemas em nosso ambiente por conta de como o hibernate trabalha. O hibernate cria constantemente classes em tempo de execução que herdam das classes da entidade e adicionam métodos que ele precisa. Vocês que trabalharam com Hibernate já devem ter visto Objetos com classes estranhas como br.com.infox.cliente.entity.Pessoa_$$_javassist_26.

O primeiro problema é que como são classes diferentes esta comparação sempre retorna false: if (getClass() != obj.getClass()). Para resolver deve-se testar com instanceof.

O segundo problema é o acesso aos campo da entidade. As vezes mesmo campos que não são lazy, só são populados quando são chamados pelo get do campo, então a comparação (idProcesso != other.idProcesso) pode retornar false, pois o valor pode não estar populado ainda.

Eu tive esse dois problemas ontem com a classe UsuarioLogin, e perdi um bom tempo para descobri isso.

Para tornar nosso equals das entidades compatíveis com o hibernate podemos reescrever ele assim:




@Override
 public boolean equals(Object obj) {
  if (this == obj)
   return true;
  if (obj == null)
   return false;
  if (!(obj instanceof UsuarioLogin))
   return false;
  UsuarioLogin other = (UsuarioLogin) obj;
  if (getIdUsuario() != other.getIdUsuario())
   return false;
  return true;
 }

Maiores explicações sobre estes problemas podem ser lidas aqui: http://blog.xebia.com/2008/03/advanced-hibernate-proxy-pitfalls/

Meu ambiente de desenvolvimento em 7 itens

Recebi um convite publico do Hugo Doria e resolvi participar deste meme retirando um item.

1) Hardware e SO
Minha maquina de desenvolvimento aqui na Infox é um Dell Latitude E6500, com 4gb de memoria. Aqui utilizamos um monitor extra, que aumenta muito a produtividade.



2) Linguagens de Programação
Java é praticamente a unica linguagem que eu utilizo. No meu projeto aqui da Infox, trabalhamos com JavaServer Faces + Seam Framework + Hibernate.
Para quem programa em Java, recomendo pesquisar sobre o Seam. O mentor dele é nada menos que o Garvin King, o cara por trás do Hibernate e que ajudou com a especificação do JPA, quase o Chuck Norris do Java.

3) Editores e IDE
Utilizamos como IDE o Jboss Developer Studio (É um empacotamento do Eclipse feito pela Red Hat, o pacote já vem com o plugin Jboss Tools e já instala e configura o Jboss Server). Antes usávamos o Eclipse + Jboss Tools sem nenhum problema nenhum.

4) Controle de Versão
Atualmente utilizamos o SVN, no passado utilizávamos os CVS e na migração tivemos vários problemas com o Plugin do SVN pro Eclipse que ná época dava problemas regularmente.

5) Softwares.

  • Navegadores: No trabalho utilizo Firefox e IE (Por causa dos clientes claro), mas pessoalmente eu migrei do Firefox para o Chrome há alguns meses.
  • SQuirreL SQL Client: Ótimo software open source para quem trabalha criando consultas de banco de dados. Possui muito recursos e o auto completar acelera muito a criação das consultas.
  • Notepad++: Melhor editor de texto que já usei, bem robusto, aceita plugins, leve, etc.
  • Foobar2000: Player de áudio bem leve e com muitos recursos, eu pessoalmente gosto de programar escutando música.
6) Música
Gosto muito de trabalhar escutando música, ela ajuda muito a me isolar dos barulhos externos e me concentrar nas tarefas mais delicadas, alem de animar e relaxar ;)
Nas férias deste ano relaxei viajando para assistir dois shows: Ozzy e Iron Maiden!
Meu gosto musical é da vertente Rock and Roll -&gt; Metal pendendo mais para o Metal. Escuto Iron Maiden, Megadeth, Slayer, Pink Floyd, etc até coisas bem mais pesadas como Deicide, Carcass e Dying Fetus ou outras mais lights como Raul Seixas.