DClick

Arquivos da categoria "Hibernate"

Utilizando funções aninhadas no Hibernate

Categorias relacionadas: Hibernate, Java

Quem utiliza Criteria já deve ter precisado utilizar funções aninhadas ( como sum(abs(propriedade)) ). Infelizmente a class Projections não dispoem deste recurso, e a classe que implementa as agregações ( AggregateProjection ) não foi projetada pensando nisso.

Baseado na class AggregateProjection implementei uma solução com um construtor que recebe um array de string com as funções a serem aninhadas na ordem do array

Leia o artigo completo »

Por Daniel Passos em 4/December/2007
1 Comentário »


No Translations

Implementando Criterion para utilizar Extract do Oracle

Categorias relacionadas: Hibernate, Java

Ontem meu amigo Filipe Sabella queria executar uma função para manipulação de data do Oracle utilizando Criteria. Algo do tipo funcao_do_oracle( columa ) = ?

O Hibernate não implementa esse tipo de funcionalidade, mas por ter seu desenvolvimento baseado em interfaces lhe possibilita extender / criar (quase) toda e qualquer funcionalidade que deseje. Depois de dar o caminho das pedras, dizendo que era "so" implementar Criterion e algumas alterações para deixarmos a mesma compativel com 1.4 chegamos a seguinte solução:

JAVA:
  1. package br.com.dclick.hibernate.criterion.oracle;
  2.  
  3. import org.hibernate.Criteria;
  4. import org.hibernate.EntityMode;
  5. import org.hibernate.Hibernate;
  6. import org.hibernate.HibernateException;
  7. import org.hibernate.criterion.CriteriaQuery;
  8. import org.hibernate.criterion.Criterion;
  9. import org.hibernate.engine.TypedValue;
  10.  
  11. public class ExtractFunctionExpression implements Criterion {
  12.  
  13.     private static final class ExtractType {
  14.  
  15.         private String function;
  16.  
  17.         private ExtractType( String function ) {
  18.             this.function = function;
  19.         }
  20.  
  21.         public String toString() {
  22.             return function.toString();
  23.         }
  24.  
  25.     }
  26.  
  27.     public static final ExtractType YEAR = new ExtractType( "YEAR" );
  28.     public static final ExtractType MONTH = new ExtractType( "MONTH" );
  29.     public static final ExtractType DAY  = new ExtractType( "DAY" );
  30.    
  31.     private String property;
  32.     private String value;
  33.     private ExtractType extractType;
  34.    
  35.     public ExtractFunctionExpression( String property, ExtractType extractType, String value ) {
  36.         this.property = property;
  37.         this.extractType = extractType;
  38.         this.value = value;
  39.     }
  40.  
  41.     public TypedValue[] getTypedValues( Criteria criteria, CriteriaQuery criteriaQuery ) throws HibernateException  {
  42.         return new TypedValue[] { new TypedValue( Hibernate.STRING, value, EntityMode.POJO ) };
  43.     }
  44.  
  45.     public String toSqlString( Criteria criteria, CriteriaQuery criteriaQuery ) throws HibernateException {
  46.         String column = criteriaQuery.getColumnsUsingProjection( criteria, property )[ 0 ];
  47.         return "( extract(" + extractType.toString() + " from " + column + " ) = ? )";
  48.     }
  49.  
  50. }

Pronto. Agora e so adicionar ao seu criterio:

JAVA:
  1. HibernateSessionFactory.getSession()
  2. .createCriteria(Venda.class)
  3. .add( new ExtractFunctionExpression("dataVenda", ExtractFunctionExpression.YEAR, "2007") )
  4. .list();

Por Daniel Passos em 14/November/2007
Nenhum Comentário »


No Translations

Por que popular apenas o necessário?

Categorias relacionadas: Hibernate, Java

Meu primeiro post neste blog gerou algumas duvidas que rendem ate hoje alguns emails sobre o porque de se popular apenas o necessário.

A maioria dos projetos onde utilizamos Hibernate, a camada de front end e de back end são Java.

Em um simples cenário onde temos uma combo a qual precisamos apenas do Id e do Nome de uma determinada classe que em seu total dispõem de muitos atributos, fazemos a pesquisa normalmente com o Hibernate que popula todos seus atributos mandamos pra camada de front end ( JSP por exemplo ) que esta preparada para utilizar apenas o Id e o Nome da class transformando apenas as informações necessários para a tela do usuário em um HTML, dispensando os dados que não serão utilizando. Tudo isso no lado do Servidor. A consulta por 2 ou 30 campos em sua maioria não faz "tanta" diferença para o banco e a transformação em dados desnecessário em HTML quando front end e back end estão no mesmo servidor ( não sendo aplicações realmente distribuídas ) também não faz "tanta" diferença.

Porem quando utilizamos flex no front end estamos trafegando uma imensidão ( exagerei? ) de dados desnecessariamente, forçando a maquina do usuário a tratar todos esses dados que em sua maioria não serão utilizados. Algumas vezes a coisa pode se tornar ainda pior quando precisamos guardar essas instâncias no model, ficando com uma serie de dados desnecessário no cliente.

Por Daniel Passos em 6/July/2007
2 Comentários »


No Translations

Implementando PropertySelector para utilizar como Example no Hibernate

Categorias relacionadas: Hibernate, Java

A algum tempo atrás alguém perguntou no GUJ se o Hibernate fazia consultas (utilizando Criteria) excluindo propriedades vazias ( "" ).

Nativamente o Hibernate não dispoem desses recurso, porem utilizando Example podemos implementar PropertySelector para faze-lo exatamente como implementação do Example.excludeZeroes()

Exemplo de PropertySelector

JAVA:
  1. public final class NotNullOrBlankPropertySelector implements PropertySelector {
  2.     public boolean include(Object object, String propertyName, Type type) {
  3.        return object!=null && (
  4.           !(object instanceof String) || !( (String) object ).equals("")
  5.        );
  6.     }
  7. }

Como utilizar

JAVA:
  1. HibernateUtil.getSession()
  2.  .createCriteria(SuaEntidade.class)
  3.  .add( Example.create(suaInstancia).setPropertySelector(new NotNullOrBlankPropertySelector()) )
  4.  .list();

Por Daniel Passos em 29/June/2007
Nenhum Comentário »


No Translations

Debugando Query do Hibernate

Categorias relacionadas: Hibernate, Java

Esta semana tive um problema com uma query que teoricamente estava certa mas não estava exatamente fazendo o que eu queria.

A primeira opção para debugar é setar o atributo show_sql = true e verificar a query que está sendo montada. Outra otima opção que pode ajudar muito e economizar tempo, é setar a propriedade format_sql = true.

Porem em nenhuma delas você terá acesso as variáveis que estão sendo setadas na sua query. Caso você tenha configurado o log4j.properties provavalmente as variaves serão gravadas em arquivo ( caso você assim o tenha configurado ) mas dificilmente está será mostrada no console. Geralmente configuramos o log4j.properties para logar tudo (ALL) com isso dificultando nosso trabalho para encontrar alguma coisa quanto realmente precisamos. O projeto caveatemptor (projeto do livro Java Persistence with Hibernate) trás uma ótima sugestão de arquivo de configuração para debugar as querys que estão sendo geradas.

# Direct log messages to stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{6}:%L - %m%n

# Root logger option
log4j.rootLogger=WARN, stdout

# Log JDBC bind parameter runtime arguments
log4j.logger.org.hibernate.type=DEBUG

A grande sacada do arquivo acima e logar apenas as classes do pacote org.hibernate.type com isso você terá em seu console a query ( formatada ) e as variáveis que foram setadas na execução da mesma. Apenas o necessário para entender o que esta acontecendo!

Por Daniel Passos em 9/April/2007
3 Comentários »


No Translations

Populando apenas o necessário com Hibernate

Categorias relacionadas: Hibernate, Java

Uma das funcionalidades do Hibernate é transformar os dados do banco em objeto (s) de acordo com as informações solicitadas, lhe poupando do trabalho de popula-los. Por padrão, o Hibernate popula todas os atributos do seu objeto, o que nem sempre é o desejado. Pense em um cenário no qual desejamos retornar ao frontend apenas os dados referente a identificação daquele objeto, como id e descrição, para popular um combo por exemplo. Não desejamos que o Hibernate retorne todos os atributos da classe gerando, assim, um trafego desnecessario em nossa rede.

Exemplificando, vamos imaginar que eu tenha uma classe de Produto que tenha dezenas de atributos. Não quero que o Hibernate popule todos eles, apenas o id e o nome do produto para enviar ao frontend. Para isso vamos utilizar 2 recursos: O setProjection, com a funcionalidade de projetar o que será requisitado na clausula select que, por padrão, sempre retorna os dados projetados como um array de objetos ao invés do próprio objeto (Produto); e o segundo recurso, setResultTransformer, que diz ao Hibernate como tratar os dados solicitados.

JAVA:
  1. Collection collection = HibernateSessionFactory.getSession()
  2. .createCriteria(Produto.class, "p")
  3. .setProjection( Projections.projectionList()
  4.     .add( Projections.property("p.id").as("id") )
  5.     .add( Projections.property("p.nome").as("nome") )
  6. )
  7. .setResultTransformer(new AliasToBeanResultTransformer(Produto.class))
  8. .list();

No exemplo acima, ao utilizarmos o método as("atributo"), criamos uma espécie de "alias" para o Hibernate saber em que propriedade ele irá "jogar" esse dado. Tal recurso é muito interessante quando desejamos selecionar dados de uma Classe e atribui-los diretamente a um DTO ou uma classe de relatório. O AliasToBeanResultTransformer pega todos os "alias" criados apartir do .as e atribui na classe que está sendo passada procurando pelo nome do atributo na mesma.

[update data="10/08/2007 14:15"]
Adicionado alias na query
[/update

Por Daniel Passos em 21/November/2006
15 Comentários »


No Translations