[HIBERNATE] Carregar apenas alguns campos da Tabela

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

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…

Veja se da certo:

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

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

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

A principio resolve sim! Já estava querendo complicar rsrs

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

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.

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

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.

[code]
public class HQL
{

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();
}

}[/code]

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);