22 votes

Comment stocker des objets dans Android Room ?

En fait, il y a deux choses que je ne comprends pas : les objets avec des objets et les objets avec des listes d'objets.

Disons que je reçois une liste d'objets du serveur. Chacun d'entre eux ressemble à ceci :

@Entity
public class BigObject {
    @PrimaryKey
    private int id;
    private User user;
    private List<SmallObject> smallObjects;
}

avec ces deux objets comme champs :

@Entity
public class User {
    @PrimaryKey
    private int id;
    private String name;
    @TypeConverters(GenderConverter.class)
    public MyEnums.Gender gender;
}

@Entity
public class SmallObject {
    @PrimaryKey (autoGenerate = true)
    private int id;
    private String smallValue;
}

Ils sont plus compliqués que cela, donc je ne peux pas utiliser @TypeConverters comme le suggère Room :

error: Cannot figure out how to save this field into database. You can consider adding a type converter for it.

Comment puis-je stocker cette structure de données dans Room ?

2 votes

En général, les entités ne détiennent pas d'autres entités en chambre, que ce soit individuellement ou sous forme de listes. Elles peuvent détenir clés étrangères à d'autres entités. D'autres structures, comme un modèle de vue, peuvent contenir toutes les entités nécessaires. C'est ainsi qu'il faut procéder, BigObject doit se débarrasser de smallObjects et remplacer user con userId comme clé étrangère. User y SmallObject aurait des clés étrangères vers BigObject . Ensuite, mettez en place un modèle de vue ou quelque chose que vous alimentez à partir de @Query Les méthodes DAO qui récupèrent les BigObject et ses liens avec d'autres pays User et de ses liens avec d'autres SmallObjects .

41voto

Jack Dalton Points 1364

Je pense que la meilleure façon de répondre à cette question est un bref aperçu des structures de stockage...

Listes

Room ne prend pas en charge le stockage de listes imbriquées à l'intérieur d'un POJO. La façon recommandée de stocker des listes est d'utiliser l'approche de la clé étrangère. Stockez la liste des objets dans une table séparée (dans ce cas, une table smallObjects) avec une clé étrangère vers leur objet parent (dans ce cas, "big_object_id"). Cela devrait ressembler à quelque chose comme ceci...

@Entity
public class BigObject {
    @PrimaryKey
    private int id;
    private User user;
    @Ignore
    private List<SmallObject> smallObjects;
}

@Entity(foreignKeys = {
            @ForeignKey(
                entity = BigObject.class,
                parentColumns = "id",
                childColumns = "big_object_fk"
            )})
public class SmallObject {
    @PrimaryKey (autoGenerate = true)
    private int id;
    private String smallValue;
    @ColumnInfo(name = "big_object_fk")
    private int bigObjectIdFk
}

Notez que nous avons ajouté le @Ignore annotaiton à List<SmallObject> car nous voulons ignorer le champ pendant la persistance de la pièce (les listes n'étant pas prises en charge). Il existe maintenant pour que, lorsque nous demandons notre liste de petits objets connexes à la base de données, nous puissions toujours les stocker dans le POJO.

À ma connaissance, cela signifie que vous effectuez deux requêtes.

BigObject b = db.BigObjectDao.findById(bOId);
List<SmallObject> s = db.smallObjectDao.findAllSOforBO(bOId);
b.setsmallObjects(s);

Il semble qu'il existe un raccourci pour cela sous la forme de @Relation

Convertisseurs de type

Ils sont destinés aux cas où vous disposez d'une structure de données complexe qui peut être aplatie sans perdre d'informations et stockée dans une seule colonne. L'objet Date en est un bon exemple. Un objet Date est complexe et contient un grand nombre de valeurs. Son stockage dans la base de données est donc délicat. Nous utilisons un convertisseur de type pour extraire la représentation en millisecondes d'un objet date et la stocker. Nous convertissons ensuite les millisecondes en objet date à la sortie, ce qui permet de conserver nos données intactes.

Embarqué

Ceci est utilisé lorsque vous voulez prendre les champs de toutes les POJO imbriquées dans votre POJO parent et les aplatir pour les stocker dans une table. un exemple :

- name
- age
- location
    - x 
    - y
- DOB

lorsqu'elle est intégrée, cette structure est stockée dans la base de données sous la forme d'un fichier :

- name 
- age 
- location_x
- location_y
- DOB

Dans un sens, Embedded existe pour vous faire gagner du temps en créant des convertisseurs de type pour chaque objet imbriqué qui contient des champs de type primaire comme String, int, float, etc....

2 votes

0 votes

@Jack Dalton L'approche ForeignKey insérera-t-elle les données dans la table appropriée à partir de la réponse du service ?

4voto

Rohit Singh Points 1934

Convertir l'objet/ List<Object> à une chaîne de caractères, puis la stocker.

Vous pouvez stocker les objets dans Room Library sous forme de chaînes de caractères. Pour cela, vous pouvez sérialiser l'objet et le stocker en tant que chaîne dans la base de données de la salle.

Du magasin à la pièce

Objet -> Serialize -> String -> Store

Lire dans la salle

String -> Deserialize ->Object -> Read

Comment sérialiser/désérialiser ?

De nombreuses options sont disponibles. Vous pouvez le faire manuellement ou utiliser une bibliothèque. Vous pouvez utiliser la bibliothèque de Google Bibliothèque GSON . Il est assez facile à utiliser.

Code : Objet -> Chaîne

public String stringFromObject(List<YourClass> list){

    Gson gson = new Gson();
    String jsonString = gson.toJson(list);
    return jsonString;

}

Code : Chaîne-> Objet

public List<YourClass> getObjectFromString(String jsonString){

    Type listType = new TypeToken<ArrayList<YourClass>>(){}.getType();
    List<YourClass> list = new Gson().fromJson(jsonString, listType);
    return list;

}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X