Android Room: Efficient way to transform json result into db object

后端 未结 3 1317
死守一世寂寞
死守一世寂寞 2021-02-19 19:35

Problem

I have a POJO parsed from an API call which looks like this

public class Article {

  public Long id;

  @Expose
  @Serialized         


        
3条回答
  •  渐次进展
    2021-02-19 20:27

    According to the documentation here "There is no limit on the number of Entity or Dao classes but they must be unique within the Database." So I think you can simply declare the different classes within your database class that extends RoomDatabase.

    Have you tried simply declaring the different POJOs as different entities and including them all in the same database class?

    For instance:

      // Article, Topic and Media are classes annotated with @Entity.
      @Database(version = 1, entities = {Article.class, Topic.class, Media.class})
      abstract class MyDatabase extends RoomDatabase {
      // ArticleDao is a class annotated with @Dao.
      abstract public ArticleDao articleDao();
      // TopicDao is a class annotated with @Dao.
      abstract public TopicDao topicDao();
      // MediaDao is a class annotated with @Dao.
      abstract public MediaDao mediaDao();
    }
    

    This may not exactly help with the redundancy, but my initial thought would be type converters as well. I've actually successfully even implemented a parcelable object as a column within my Room Database using TypeConverters and a single Dao.

    Have you tried using Gson in your TypeConverter class? I believe this article addresses your question more directly. It's a guide to storing objects in a room database. Again, the trick is in the type converters and declaring your object as the type token for Gson. For instance:

    public class Converters {
       @TypeConverter
       public static List fromStringToList(String mediaListString) {
          Type myType = new TypeToken>() {}.getType();
          return new Gson().fromJson(mediaListString, myType);
       }
       @TypeConverter
       public static String fromMediaListToString(List mediaItems) {
          if (mediaItems== null || mediaItems.size() == 0) {
            return (null);
          }
          Gson gson = new Gson();
          Type type = new TypeToken>() {
          }.getType();
          String json = gson.toJson(mediaItems, type);
          return json;
       }
    }
    

    That addresses the things you've tried. Now on to your statement "I believe I need to transform the object to one which matches the database entity model." Actually, not necessarily. You can use the @Ignore annotation for different creation instances or implementations of your entity, so long as there is at least one default constructor that includes the primary key of the entry. In your case:

    @Entity(foreignKeys = { 
          @ForeignKey(entity = Article.class, parentColumns = "id", childColumns = 
          "articleId"), 
          @ForeignKey(entity = Topic.class, parentColumns = "id", childColumns = 
          "topicId"),
          @ForeignKey(entity = Media.class, parentColumns = "id", childColumns = 
          "mediaId")
    }
    
    public class ArticlesEntry {
    
    @PrimaryKey
    public Long articleId; 
    @ColumnInfo(name = "topic_id")
    public Long topicId;
    @ColumnInfo(name = "media_id")
    public Long mediaId;
    
    private Article articleObject;
    private Media mediaObject;
    
    //default constructor
    public ArticlesEntry(int id) {
        this.articleId = id;
    }
    
    //You can call this anytime you add to the database with media object input
    @Ignore
    public ArticlesEntry(int id, Media inMedia) {
        this.articleId = id;
        this.mediaObject= inMedia;
    }
    //You can create many of these and insert as needed, the left out variables of the 
    //are null, note that id has to be passed b/c your primary key isn't set to 
    //autogenerate
    @Ignore
    public ArticlesEntry(int id, Article inArticle) {
        this.articleId = id;
        this.articleObject= articleObject;
    }
    //Or both objects:
    @Ignore
    public ArticlesEntry(int id, Media inMedia, Article inArticle) {
        this.articleId = id;
        this.mediaObject = inMedia;
        this.articleObject= articleObject;
    }
    
    //getters and setters here...
    
    }
    

    If you create your ArticlesEntry like above, you'll need to make and include the different TypeConverters, which can all be within the same class and imported to the specific DB with @TypeConverters(MyConverters.class). Hope this helps!

提交回复
热议问题