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