maio 2008


Como desenvolvedor Web estou sempre à procura de ferramentas que me auxiliem a criar, modificar ou entender a estrutura das páginas e assim obter como resultado uma interface melhor.

E não custa lembrar que, além de linguagens, frameworks, IDEs e todo o resto, temos nessa área um outro importante personagem: o browser (ou navegador, se assim prefirirem). Ele pode ser ao mesmo tempo o vilão, ao forçar a caça a “recursos técnicos” para driblar bugs (não IE mesmo?), ou o mocinho, ao proporcionar mecanismos auxiliares para que o desenvolvedor tenha mais liberdade e poder para alcançar os resultados desejados. É preciso saber escolher… E para mim o Firefox tem sido uma ótima escolha!

Disponibilizando vários e interessantes plugins (ou complementos), este navegador é hoje o preferido da maioria dos programadores e geeks pelo mundo. E para quem necessita fazer manutenção em páginas web, o aclamado plugin Firebug (que em breve deverá receber um post mostrando suas funcionalidades) é praticamente obrigatório.

Mas além dos plugins, existem outras pequenas jóias personalizáveis que podem ser agregadas aos navegadores…

Os bookmarklets

Resumindo a estória, bookmarklets são pequenos trechos de código javascript que podem ser adicionados aos links favoritos e que proporcionam algum comportamento desejado para a página atual quando são executados. Geralmente estão disponíveis na Internet como links que podem ser arrastados diretamente para a barra de favoritos para que fiquem disponíveis sempre que necessários. Aproveito para avisar que alguns só funcionam no Firefox…

Dentre os que mantenho sempre à mão estão o CSS Reloader, que recarrega as folhas de estilo da página sem que seja necessário um refresh completo, e o Design, que auxilia na definição ou verificação de layouts.

E agora o motivo deste post… Apresento minha mais nova “aquisição”: o jQuerify.

Este bookmarklet possibilita disponibilizar em qualquer página o framework javascript jQuery, mesmo que ela não o importe inicialmente!!

Agora você pode perguntar: “Sim, e daí??”

E daí que o jQuery possibilita você manipular qualquer coisa em um documento HTML, e agora você tem todo esse poder em qualquer página que você precise! Executando o jQuerify e em seguida utilizando o console javascript disponível no Firebug, você tem inúmeras maneiras de modificar uma página que você esteja visitando.

Posso estar exagerando um pouco na minha empolgação, mas depois que você começa a usar o jQuery e percebe que o conhecimento sobre seletores CSS pode ser agregado a funções javascript com possibilidades infinitas (eita!!), quer ter isso sempre disponível… Mesmo que seja só para “ajustar” o site dos outros para ficar do jeito que você prefere…

Creio que a maioria dos desenvolvedores Java alguma vez se deparou com o trabalhoso problema de persistir informações em um banco de dados relacional. E muitos deles descobriram no Hibernate uma (relativamente) simples e eficiente solução.

Este framework de mapeamento objeto-relacional tornou-se o padrão de facto para realizar o gerenciamento de entidades persistentes em aplicações Java (depois do fiasco dos Entity Beans), tendo muitas de suas idéias adotadas na especificação da JPA. Além da facilidade de definição dos mapeamentos e de uma completa API para a realização de consultas, um dos seus pontos fortes é a ótima documentação disponível.

Entretanto, existem algumas funcionalidades para as quais esta documentação é quase inexistente. E dentre elas temos os esquecidos, mas bastante úteis, transformadores de resultados.

O problema!

Para entender a utilidade deste recurso, considere a seguinte consulta de alunos utilizando HQL (os detalhes podem ser abstraídos sem maiores problemas):

...
List resultado = session.createQuery("select matricula, nome, curso.nome from Aluno").list();
...

Com esta simples projeção restringimos a busca e aumentamos a performance da consulta de todos os alunos persistidos. Entretanto, teremos como resultado final uma lista de Object[] que precisaria ser manipulada para extrair os diversos campos.

Esta manipulação podería ser um laço para percorrer a lista resultante e, para cada array de objetos, instanciar DTOs ou entidades. Simples, mas nada divertido…

Ou então poderíamos criar um construtor para aluno que aceite os parâmetros da consulta e substituir a query por "select new Aluno(matricula, nome, curso.nome) from Aluno" . Dessa forma teríamos uma lista de alunos pronta, mas que necessitaria de novos construtores a cada novo parâmetro necessário.

Para resolver problemas deste tipo é que vamos em busca dos ResultTransformers.

A interface ResultTransformer

Escondida na API do Hibernate existe uma interface que possibilita transformar o resultado de uma consulta, seja ela com Criteria, HQL ou SQL (o suporte aos dois últimos foi adicionado na versão 3.2) que utilize projeções em uma representação mais prática do que, por exemplo, uma lista de Object[]. Apresento então a pequena ResultTransformer:

public interface ResultTransformer extends Serializable {
	public Object transformTuple(Object[] tuple, String[] aliases);
	public List transformList(List collection);
}

Os dois métodos especificados são aplicados em diferentes momentos para transformar o resultado de uma query: transformTuple é chamado durante o processamento inicial do resultado, com acesso às colunas retornadas pela consulta e aos aliases especificados para cada uma delas (se existirem); no caso de transformList a chamada é imediatamente antes do Hibernate retornar o resultado de uma consulta.

Alguns transformadores prontos para usar

Mas de que adianta uma interface sem implementações, não é? Felizmente o Hibernate disponibiliza algumas classes prontas para serem usadas em seus projetos.

Voltemos ao nosso problema: como não ter trabalho para manipular o resultado de consultas com projeção?

A primeira opção é o AliasToBeanResultTransformer. Este transformador mapeia aliases (se você não sabe que o são alias, aguarde mais um pouco para entender com o exemplo) de colunas em atributos de objetos pertencentes à classe definida em seu construtor, populando-os através de métodos setters (via setter injection). A utilização pode ser vista no exemplo abaixo:

...
List<AlunoDTO> alunos = session
    .createQuery( "select matricula as matricula, nome as nomeAluno, curso.nome as nomeCurso from Aluno" )
    .setResultTransformer(new AliasToBeanResultTransformer(AlunoDTO.class))
    .list();
...

Comparando com o código original vemos algumas diferenças. A primeira é a utilização da palavra-chave “as”. Esta é a forma de definir aliases (apelidos) para as colunas que serão utilizados para popular instâncias da classe AlunoDTO através de setters no estilo setNomeAluno() ou setNomeCurso().

A segunda diferença é a chamada ao método setResultTransformer() da interface Query. Com ela é possível determinar uma estratégia de transformação de resultados de acordo com a necessidade da consulta. Neste caso, informamos uma instância de AliasToBeanResultTransformer, definido para transformar as colunas em objetos do tipo AlunoDTO.

Como alternativa para a criação de DTOs ou de métodos setters em entidades podemos utilizar o AliasToEntityMapResultTransformer. Com ele a lista de tuplas será transformada em uma lista de mapas, onde cada cada um deles terá um conjunto de entradas alias => valor_da_coluna. Dessa forma temos uma representação mais fácil de ser manipulada do que a original.

Logo abaixo vê-se um exemplo de seu emprego:

...
List<Map<String,Object>> mapaAlunos= session
    .createQuery( "select matricula as matricula, nome as nomeAluno, curso.nome as nomeCurso from Aluno" )
    .setResultTransformer(new AliasToEntityMapResultTransformer())
    .list();
...

Viram como este recurso pode ser útil? Além destes dois apresentados existem mais transformadores que podem ser utilizados em outros casos, como o DistinctRootEntityResultTransformer, empregado para evitar duplicidade de entidades no resultado. E se ainda não for suficente, sempre é possível criar novas estratégias implementando a interface ResultTransformer.