2012-08-16 8 views
7

Sto cercando un modo per eseguire una query che richiede un JOIN. C'è un modo per farlo in una dichiarazione preparata, o è la rawQuery l'unica opzione che ho. Se rawQuery è l'unica opzione, esiste un modo per associare automaticamente gli oggetti restituiti agli oggetti del Dao in fase di implementazione.ORMLite JOINs o mapping automatico rawQuery

Ho esaminato i documenti e gli esempi ma non riesco a trovare nulla che mi consenta di mappare il risultato del database non elaborato in una classe di oggetti ORM.

+1

FYI Daniel. ORMLite 4.22 è stato appena rilasciato e supporta semplici query JOIN. – Gray

+0

In precedenza avevo ORMLite 4.23 che non supportava le query JOIN. Rivedendo le date di rilascio e il timestamp del tuo commento, credo che intendessi dire che ORMLite 4.26, rilasciato il 26/09/12, è stata la prima versione a supportare semplici query JOIN. Ho appena aggiornato alla 4.45, che ha sicuramente UNISCITI. –

risposta

15

Supporti ORMLite simple JOIN queries. È inoltre possibile utilizzare raw-queries per ottenere ciò.

È possibile utilizzare lo Dao.getRawRowMapper() per mappare le query come si è trovato oppure è possibile creare un programma di mappatura personalizzato. La documentazione ha il seguente codice di esempio che mostra come eseguire il mapping del String[] nel vostro oggetto:

GenericRawResults<Foo> rawResults = 
    orderDao.queryRaw(
    "select account_id,sum(amount) from orders group by account_id", 
    new RawRowMapper<Foo>() { 
      public Foo mapRow(String[] columnNames, 
       String[] resultColumns) { 
       return new Foo(Long.parseLong(resultColumns[0]), 
        Integer.parseInt(resultColumns[1])); 
     } 
    }); 
+0

Grazie a @Gray. Avevo trovato tutto il materiale personalizzato per la mappatura delle righe, ma volevo semplicemente mapparlo automaticamente a un oggetto che avevo già definito. L'opzione JOIN di QueryBuilder sarà la prossima sulla mia lista dei desideri! Qualche parola su quando/se arriverà? – DanO

+0

Vuoi iniziare una discussione su omlite-dev? Sono pronto a scriverlo. Quello che sarà più difficile è usare il join per idratare i sottooggetti. Ma inizia la discussione e ti risponderò: https://groups.google.com/forum/?fromgroups#!forum/ormlite-dev – Gray

+1

Creato il thread. – DanO

8

Ho trovato un modo per mappare automaticamente un set di risultati su un oggetto modello.

// return the orders with the sum of their amounts per account 
GenericRawResults<Order> rawResults = 
    orderDao.queryRaw(query, orderDao.getRawRowMapper(), param1) 

// page through the results 
for (Order order : rawResults) { 
    System.out.println("Account-id " + order.accountId + " has " 
    + order.totalOrders + " total orders"); 
} 

rawResults.close(); 

La chiave è quello di tirare il mapper fila dall'oggetto Dao utilizzando getRawRowMapper(), che si occuperà della mappatura per voi. Spero che questo aiuti chiunque lo trovi.

Mi piacerebbe ancora la possibilità di fare join all'interno dello QueryBuilder ma fino a quando non è supportato, questa è la prossima cosa migliore a mio parere.

0

mappatura automatica di query Raw

ho avuto problema dei campi di mappatura da personalizzati selezionare le colonne che non sono tornare presente in qualsiasi modello di tabella. Quindi ho personalizzato RawRowMapper che può mappare i campi dalla query personalizzata al modello personalizzato. Questo è utile quando hai una query che ha campi che non corrispondono a nessun modello di mappatura delle tabelle.

Questo è RowMapper che esegue la mappatura interrogazione automatica:

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

E qui viene il utilizzo:

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

Ciò restituirà List<Model> con righe di risultati mappati modella Se colonna di interrogazione nomi e @DatabaseField(columnName sono gli stessi

Problemi correlati