mapeo automático consulta Raw
tuve problema de la asignación de campos de encargo SELECT que devuelven columnas que no son presente en cualquier modelo de mesa. Así que hice personalizado RawRowMapper
que puede mapear campos de consulta personalizada a modelo personalizado. Esto es útil cuando tiene una consulta que tiene campos que no corresponden a ningún modelo de mapeo de tablas.
Ésta es RowMapper que realiza el mapeo consulta automática:
public class GenericRowMapper<T> implements RawRowMapper<T> {
private Class<T> entityClass;
private Set<Field> fields = new HashSet<>();
private Map<String, Field> colNameFieldMap = new HashMap<>();
public GenericRowMapper(Class<T> entityClass) {
this.dbType = dbType;
this.entityClass = entityClass;
Class cl = entityClass;
do {
for (Field field : cl.getDeclaredFields()) {
if (field.isAnnotationPresent(DatabaseField.class)) {
DatabaseField an = field.getAnnotation(DatabaseField.class);
fields.add(field);
colNameFieldMap.put(an.columnName(), field);
}
}
cl = cl.getSuperclass();
} while (cl != Object.class);
}
@Override
public T mapRow(String[] columnNames, String[] resultColumns) throws SQLException {
try {
T entity = entityClass.newInstance();
for (int i = 0; i < columnNames.length; i++) {
Field f = colNameFieldMap.get(columnNames[i]);
boolean accessible = f.isAccessible();
f.setAccessible(true);
f.set(entity, stringToJavaObject(f.getType(), resultColumns[i]));
f.setAccessible(accessible);
}
return entity;
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
public Object stringToJavaObject(Class cl, String result) {
if (result == null){
return null;
}else if (cl == Integer.class || int.class == cl) {
return Integer.parseInt(result);
} else if (cl == Float.class || float.class == cl) {
return Float.parseFloat(result);
} else if (cl == Double.class || double.class == cl) {
return Double.parseDouble(result);
} else if (cl == Boolean.class || cl == boolean.class) {
try{
return Integer.valueOf(result) > 0;
}catch (NumberFormatException e){
return Boolean.parseBoolean(result);
}
} else if (cl == Date.class) {
DateLongType lType = DateLongType.getSingleton();
DateStringType sType = DateStringType.getSingleton();
try {
return lType.resultStringToJava(null, result, -1);
} catch (NumberFormatException e) {
try {
return sType.resultStringToJava(null, result, -1);
} catch (SQLException e2) {
throw new RuntimeException(e);
}
}
} else {
return result;
}
}
}
Y aquí está el uso :
class Model{
@DatabaseField(columnName = "account_id")
String accId;
@DatabaseField(columnName = "amount")
int amount;
}
String sql = "select account_id,sum(amount) amount from orders group by account_id"
return queryRaw(sql,new GenericRowMapper<>(Model.class)).getResults()
Esto devolverá List<Model>
con filas de resultados asignados al modelo si columna de la consulta nombres y @DatabaseField(columnName
son los mismos
FYI Daniel. Acaba de lanzar ORMLite 4.22, que admite consultas JOIN simples. – Gray
Anteriormente tenía ORMLite 4.23 que no admitía las consultas JOIN. Al revisar las fechas de publicación y la marca de tiempo de su comentario, creo que quiso decir que ORMLite 4.26, publicado el 26/09/12, fue la primera versión compatible con consultas simples de JOIN. Acabo de actualizar a 4.45, que definitivamente tiene JOIN. –