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

后端 未结 3 1336
死守一世寂寞
死守一世寂寞 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:26

    You can use @Embedded annotation for your related POJO which refers to another class.

    You can do like this:

    Article.java

    @Entity(tableName = "Article")
    public class Article {
        @ColumnInfo (name = "article_id")
        public Long id;
    
        @Expose
        @SerializedName("section")
        public String section;
    
        @Expose
        @SerializedName("title")
        public String title;
    
        @Expose
        @SerializedName("topics")
        public List<String> topics;
    
        @Embedded // We need relation to Media table
        @Expose
        @SerializedName("media")
        public List<Media> media;
    }
    

    Media.java

    public class Media {
        @ColumnInfo (name = "media_id")
        public Long id;
    }
    

    So now on, you can directly use this POJO as Entity for ROOM.


    Please note:

    Though i'm not sure about how you'll handle that relation (because, Media obj is in list for Article class, you'll need to use type converter for that)

    Reference from here

    0 讨论(0)
  • 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<Media> fromStringToList(String mediaListString) {
          Type myType = new TypeToken<List<Media>>() {}.getType();
          return new Gson().fromJson(mediaListString, myType);
       }
       @TypeConverter
       public static String fromMediaListToString(List<Media> mediaItems) {
          if (mediaItems== null || mediaItems.size() == 0) {
            return (null);
          }
          Gson gson = new Gson();
          Type type = new TypeToken<List<VideoParcelable>>() {
          }.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!

    0 讨论(0)
  • 2021-02-19 20:28

    All you have to do is use @Embedded annotation for your POJO(Model Class) which will refer to another class. then create a type converter class.

     @Embedded(prefix = "media")
    private Meida media;
    
    @TypeConverters({TypeConvertorClass.class})
    @Database(entities = {Article .class,Media.class}, version = 1, exportSchema = false)
    public abstract class `DataBaseExample` extends RoomDatabase {
    }
    
    
    public class Converters {
        @TypeConverter
        public static ArrayList<String> fromString(String value) {
            Type listType = new TypeToken<ArrayList<String>>() {}.getType();
            return new Gson().fromJson(value, listType);
        }
    
        @TypeConverter
        public static String fromArrayLisr(ArrayList<String> list) {
            Gson gson = new Gson();
            String json = gson.toJson(list);
            return json;
        }
    }
    
    
        public class TypeConvertorClass {
        @TypeConverter
        public static Media getMedia(String longId) {
            return longId== null ? null : new Meida();
        }
    
    }
      @Entity(tableName = "Article")
        public class Article {
            @ColumnInfo (name = "article_id")
            public Long id;
    
            @Expose
        @SerializedName("section")
        public String section;
    
        @Expose
        @SerializedName("title")
        public String title;
    
        @Expose
        @SerializedName("topics")
        public List<String> topics;
    
       @Embedded(prefix = "media") // We need relation to Media table
        @Expose
        @SerializedName("media")
        public List<Media> media;
    }
    
    public class Media {
        @ColumnInfo (name = "media_id")
        public Long id;
    }
    
    0 讨论(0)
提交回复
热议问题