Android Room: come modellare le relazioni?

Ho appena iniziato a lavorare con Room e anche se tutto sembra essere piuttosto intuitivo, attualmente non capisco esattamente come gestire le relazioni.

Poiché SQLite è un database relazionale, è ansible specificare le relazioni tra gli oggetti. Anche se la maggior parte delle librerie ORM consente agli oggetti quadro di fare riferimento l’un l’altro, Room lo proibisce esplicitamente. Anche se non è ansible utilizzare le relazioni dirette, Room consente comunque di definire i vincoli di chiave esterna tra quadro. (Fonte: https://developer.android.com/topic/libraries/architecture/room.html#no-object-references )

  1. Come dovresti modellare una relazione da molti a molti o da uno a molti ?
  2. Come sarebbe questo in pratica (esempio DAO + Entità)?

Puoi usare @Relation annotazione @Relation per gestire le relazioni in Room.

Un’annotazione di convenienza che può essere utilizzata in un Pojo per recuperare automaticamente le entity framework di relazione. Quando il Pojo viene restituito da una query, tutte le sue relazioni vengono anche recuperate da Room.

Vedi il documento.

(Il documento di Google ha esempi confusi, ho scritto i passaggi e alcune spiegazioni di base alla mia altra risposta. Puoi verificarlo )

Ho creato un semplice metodo di convenienza che popola manualmente una relazione uno a molti. Quindi, ad esempio se ne hai uno a molti tra Paese e Città, puoi utilizzare il metodo per popolare manualmente la proprietà cityList in Paese.

 /** * @param tableOne The table that contains the PK. We are not using annotations right now so the pk should be exposed via a getter getId(); * @param tableTwo The table that contains the FK. We are not using annotations right now so the Fk should be exposed via a getter get{TableOneName}Id(); eg. getCountryId(); * @param  Table One Type * @param  Table Two Type * @throws NoSuchFieldException * @throws IllegalAccessException * @throws NoSuchMethodException * @throws InvocationTargetException */ private static  void oneToMany(List tableOne, List tableTwo) throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { String tableOneName = tableOne.get(0).getClass().getSimpleName(); String tableTwoName = tableTwo.get(0).getClass().getSimpleName(); for (T1 t1 : tableOne) { Method method = t1.getClass().getMethod("getId"); Integer pkId = (Integer) method.invoke(t1); List listForCurrentId = new ArrayList<>(); for (T2 t2 : tableTwo) { Method fkMethod = t2.getClass().getDeclaredMethod("get".concat(tableOneName).concat("Id")); Integer fkId = (Integer) fkMethod.invoke(t2); if (pkId == fkId) { listForCurrentId.add(t2); } } Method tableTwoList = t1.getClass().getMethod("set".concat(tableTwoName).concat("List"), List.class); tableTwoList.invoke(t1, listForCurrentId); } } 

Questo è come lo uso.

  SystemDefaults systemDefaults = new SystemDefaults(); return Single.zip(systemDao.getRoles(), systemDao.getCountries(), systemDao.getCities(), (roles, countries, cities) -> { systemDefaults.setRoles(roles); *ConvenienceMethods.oneToMany(countries,cities);* systemDefaults.setCountries(countries); return systemDefaults; });