[HIBERNATE] Carregar apenas alguns campos da Tabela

9 respostas
R

Considerando que eu tenho uma tabela com 40 colunas (sim poderia estar modelado melhor… mas agora não tenho como modificar). queria carregar apenas 5~6 colunas principais para exibir na listagem, e só quando selecionar o registro carrego o objeto inteiro.

Ex:
“SELECT nome, endereco, cidade, bairro FROM Cliente”

O Hibernate irá me retornar um Object[] com as informações do nome, endereco, cidade e bairro e eu preciso criar o objeto “na mão”.

Tem algo pronto para carregar o objeto?

Obs: Vi na documentação que é possivel colocar a propriedade lazy na coluna, mas não achei essa anotação

9 Respostas

F

Muito bom caso Rafael…
Nunca precisei usar…mas acho q não tem LAZY de coluna…vou tentar pesquisar aqui para te ajudar…
Eu acho que, baseado nos princípios e motivações ORM, esta situação sua não se encaixa muito bem com ORM…ou seja, para estes casos vc não deveria esta usando framework ORM…Mas vamos ver oq da…

F

Veja se da certo:

R

Opa… como eu não achei essa anotação? rsrs

Retirado do docs sobre @Basic como Lazy:
“Usually you don’t need to lazy simple properties (not to be confused with lazy association fetching). The recommended alternative is to use the projection capability of JP-QL (Java Persistence Query Language) or Criteria queries.”

Vou continuar procurando usando Projections e Critertias… se não vou criar um “montador de objetos” genéricos rsrs

R

Anotei uma coluna com @Basic(fetch = FetchType.LAZY), mas igual ela foi “carregada” junto na pesquisa

R

Rafael,dá uma olhada em Projections,acho q resolve teu problema.

R

A principio resolve sim! Já estava querendo complicar rsrs

Exemplo:
http://www.roseindia.net/hibernate/projections/hibernate-projections.shtml

R

Com HQL será que não rola algo semelhante com Projections?

Esses tempos estava com um “bug” usando Criteria que duplicava registros e com o HQL não duplicava. Desde então, passei a só usar HQL :S Estou com receio que volte a duplicar registros.

R

Problema continua… Projections não resolverá o problema.
Pois o resultado é um vetor de objetos.

Usar Projections é equivalente a fazer a query selecionando os campos, ex: "SELECT campo FROM tabela"
Ambas resultam um vetor de objetos

R

Como tanto Projections quanto HQL retornam Object[] e não o objeto em questão.
Eu teria que montar o objeto na mão.

Por isso criei uma classe para me ajudar nisso, ela tem duas utilidades:

1) Criar HQL's com DSL de uma maneira "parecida" com Criteria
2) Montar esses objetos

Segue abaixo o código, qq vocês acham?

Obs: A exceção é uma genérica que utilizo aqui para disparar a mensagem para a interface.
Obs2: O método load precisa ser refatorado.

public class HQL<T>
{

	private Class<?> classe;
	private List<String> fields = new ArrayList<String>();
	private List<String> conditions = new ArrayList<String>();
	private Order order;
	
	public HQL(Class<?> classe)
	{
		this.classe = classe;
	}
	
	public HQL<T> fields(String... columns) 
	{
		for(String column : columns)
		{
			fields.add(column);
		}
		
		return this;
	}
	
	public HQL<T> conditions(String... parameters) 
	{
		for(String condition : parameters)
		{
			conditions.add(condition);
		}
		
		return this;
	}
	
	public HQL<T> orderBy(Order order)
	{
		this.order = order;
		return this;
	}
	
	public String build()
	{
		StringBuilder query = new StringBuilder();
		
		if(!fields.isEmpty())
		{
			query.append("SELECT ");
			
			for(String field : fields)
			{
				if(fields.indexOf(field) != 0)
					query.append(",");
				
				query.append(field);
			}
			
			query.append(" ");
		}
		
		query.append("FROM ").append(getTableName());
		
		if (!conditions.isEmpty()) 
		{
			for(String condition : conditions)
			{
				if(conditions.indexOf(condition) != 0)
					query.append(" AND ");
				else
					query.append(" WHERE ");
				
				query.append(condition);
			}
		}
		
		if(order != null)
		{
			query.append(" ORDER BY ").append(order.toString());
		}
		
		return query.toString();
	}
	
	public List<T> load(List<Object[]> registros) throws FlexException
	{
		List<T> objetos = new ArrayList<T>();
		
		for(Object[] registro : registros)
		{
			objetos.add( load(registro) );
		}
		
		return objetos;
	}
	
	//TODO Implementar função recursiva para conseguir preencher mais de um nivel ex: cliente.estado.codigo
	public T load(Object[] registro) throws FlexException
	{
		Object objeto;
		try 
		{
			objeto = createObject(classe);
			
			for(int i = 0; i < registro.length; i++)
			{
				String fieldName = fields.get(i);
			
				if(fieldName.contains("."))
				{
					String[] columns = fieldName.split("\\.");
					
					Field parentField = getField(classe, columns[0]);
					Class<?> parentClass = parentField.getType();
					
					Object parent = createObject(parentClass);
					
					Field field = getField(parentClass, columns[1]);
					field.setAccessible(true);
					field.set(parent, registro[i]);
					
					parentField.setAccessible(true);
					parentField.set(objeto, parent);
				}
				else
				{
					Field field = getField(classe, fieldName);
					field.setAccessible(true);
					field.set(objeto, registro[i]);
				}
			}
			
			return (T) objeto;
		} 
		catch (IllegalAccessException e) 
		{
			throw new FlexException("Erro ao carregar objeto", e);
		}
	}
	
	private Field getField(Class<?> classe, String fieldName) throws FlexException
	{
		try 
		{
			return classe.getDeclaredField(fieldName);
		} 
		catch (SecurityException e) 
		{
			throw new FlexException("Erro ao carregar objeto", e);
		} 
		catch (NoSuchFieldException e) 
		{
			throw new FlexException("Erro ao carregar objeto", e);
		}
	}

	private Object createObject(Class<?> clazz) throws FlexException
	{
		try 
		{
			return clazz.newInstance();
		} 
		catch (InstantiationException e) 
		{
			throw new FlexException("Erro ao carregar objeto", e);
		} 
		catch (IllegalAccessException e) 
		{
			throw new FlexException("Erro ao carregar objeto", e);
		}
	}
	
	private String getTableName()
	{
		return classe.getSimpleName();
	}
	
}

Exemplo de Utilização:

HQL<Pedido> query = new HQL<Pedido>(Pedido.class).fields("codigo", "cliente.nome", "data_faturamento", "comprador").orderBy(Order.desc("codigo")); 
String hql = query.build();
List<Object[]> registros = ... usa qualquer meio para pesquisar
List<Pedido> pedidos = query.load(registros);
Criado 11 de agosto de 2011
Ultima resposta 11 de ago. de 2011
Respostas 9
Participantes 3