在 Room 中访问和存储多个 POJO 类
Accessing and Storing multiple POJO classes in Room
我有多个 POJO classes 作为主 POJO class 的类型,我用它来使用 Retrofit 解析 json 数据。所以我为第一级 Pojo 提供了类型转换器,但我在读取存储的数据时遇到了问题,因为它的格式不正确。
这是我的 POJO class
@Entity(tableName = "entry")
public class Entry implements Parcelable {
@NonNull
@PrimaryKey
@SerializedName("id")
private FeedID feedId;
@SerializedName("title")
private Title EntryTitle;
@SerializedName("im:image")
private List<Image> image;
@SerializedName("summary")
private Summary summary;
public Entry(){}
public FeedID getFeedId() {
return feedId;
}
public void setFeedId(FeedID feedId) {
this.feedId = feedId;
}
public Title getEntryTitle() {
return EntryTitle;
}
public void setEntryTitle(Title entryTitle) {
this.EntryTitle = entryTitle;
}
public List<Image> getImage() {
return image;
}
public void setImage(List<Image> image) {
this.image = image;
}
public Summary getSummary() {
return summary;
}
public void setSummary(Summary summary) {
this.summary = summary;
}
@SuppressWarnings("unused")
public static final Parcelable.Creator<Entry> CREATOR = new Parcelable.Creator<Entry>() {
@Override
public Entry createFromParcel(Parcel in) {
return new Entry(in);
}
@Override
public Entry[] newArray(int size) {
return new Entry[size];
}
};
protected Entry(Parcel in) {
feedId = (FeedID) in.readValue(FeedID.class.getClassLoader());
EntryTitle = (Title) in.readValue(Title.class.getClassLoader());
if (in.readByte() == 0x01) {
image = new ArrayList<Image>();
in.readList(image, Image.class.getClassLoader());
} else {
image = null;
}
summary = (Summary) in.readValue(Summary.class.getClassLoader());
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeValue(feedId);
dest.writeValue(EntryTitle);
if (image == null) {
dest.writeByte((byte) (0x00));
} else {
dest.writeByte((byte) (0x01));
dest.writeList(image);
}
dest.writeValue(summary);
}
public class Title implements Parcelable {
private String label;
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
@SuppressWarnings("unused")
public final Parcelable.Creator<Title> CREATOR = new Parcelable.Creator<Title>() {
@Override
public Title createFromParcel(Parcel in) {
return new Title(in);
}
@Override
public Title[] newArray(int size) {
return new Title[size];
}
};
protected Title(Parcel in) {
label = in.readString();
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(label);
}
}
public class Image implements Parcelable {
private String label;
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
@SuppressWarnings("unused")
public final Parcelable.Creator<Image> CREATOR = new Parcelable.Creator<Image>() {
@Override
public Image createFromParcel(Parcel in) {
return new Image(in);
}
@Override
public Image[] newArray(int size) {
return new Image[size];
}
};
protected Image(Parcel in) {
label = in.readString();
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(label);
}
}
public class Summary implements Parcelable {
private String label;
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
@SuppressWarnings("unused")
public final Parcelable.Creator<Summary> CREATOR = new Parcelable.Creator<Summary>() {
@Override
public Summary createFromParcel(Parcel in) {
return new Summary(in);
}
@Override
public Summary[] newArray(int size) {
return new Summary[size];
}
};
protected Summary(Parcel in) {
label = in.readString();
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(label);
}
}
public class FeedID implements Parcelable {
private Attributes attributes;
public Attributes getAttributes() {
return attributes;
}
public void setAttributes(Attributes attributes) {
this.attributes = attributes;
}
@SuppressWarnings("unused")
public final Parcelable.Creator<FeedID> CREATOR = new Parcelable.Creator<FeedID>() {
@Override
public FeedID createFromParcel(Parcel in) {
return new FeedID(in);
}
@Override
public FeedID[] newArray(int size) {
return new FeedID[size];
}
};
protected FeedID(Parcel in) {
attributes = (Attributes) in.readValue(Attributes.class.getClassLoader());
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeValue(attributes);
}
}
public class Attributes implements Parcelable {
@SerializedName("im:id")
private String id;
public String getIm() {
return id;
}
public void setIm(String im) {
this.id = im;
}
@SuppressWarnings("unused")
public final Parcelable.Creator<Attributes> CREATOR = new Parcelable.Creator<Attributes>() {
@Override
public Attributes createFromParcel(Parcel in) {
return new Attributes(in);
}
@Override
public Attributes[] newArray(int size) {
return new Attributes[size];
}
};
protected Attributes(Parcel in) {
id = in.readString();
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(id);
}
}
}
这是我的 TypeConverter class
public class RoomTypeConverters {
@TypeConverter
public static String toString(Entry.Title value) {
Gson gson = new Gson();
String json = gson.toJson(value);
return json;
}
@TypeConverter
public static Entry.Title toTitle(String value) {
Type listType = new TypeToken<Entry.Title>() {
}.getType();
return new Gson().fromJson(value, listType);
}
@TypeConverter
public static String toString(Entry.FeedID value) {
Gson gson = new Gson();
String json = gson.toJson(value);
return json;
}
@TypeConverter
public static Entry.FeedID toFeedID(String value) {
Type listType = new TypeToken<Entry.FeedID>() {
}.getType();
return new Gson().fromJson(value, listType);
}
@TypeConverter
public static String toString(Entry.Summary value) {
Gson gson = new Gson();
String json = gson.toJson(value);
return json;
}
@TypeConverter
public static Entry.Summary toSummary(String value) {
Type listType = new TypeToken<Entry.Summary>() {
}.getType();
return new Gson().fromJson(value, listType);
}
@TypeConverter
public static String toString(List<Entry.Image> value) {
Gson gson = new Gson();
String json = gson.toJson(value);
return json;
}
@TypeConverter
public static List<Entry.Image> toImage(String value) {
Type listType = new TypeToken<Entry.Summary>() {
}.getType();
return new Gson().fromJson(value, listType);
}
}
我是否必须只为一个字段创建多个这样的 POJO?我们还有其他选择吗?
是的,要保存 POJO,您必须 为其定义 class(内部或正常 class)。
但是我从你的数据模式中了解到你有一个可能 复杂的 数据存储服务器端并且你想使用 子集 在你的应用程序中的数据。您的 POJO 可以简化,因此您可以创建一个名为 EntryRecord
的 Class,并为其定义一个简单的 setter 和 getter,如下所示:
@Entity(tableName = "entry")
public class EntryRecord {
@NonNull
@PrimaryKey
@SerializedName("id")
private String feedId;
@SerializedName("title")
private StringEntryTitle;
@SerializedName("im:image")
private String[] image;
@SerializedName("summary")
private String summary;
public EntryRecord(Entry entry){
//Resolve primitive values from Entry class attributes..
}
public Entry getEntry(){
Entry entry = new Entry();
//Resolve entry values from primitive ones...
return entry ;
}
}
,现在你所要做的就是使用这个class来保存和恢复你的数据,你甚至可以让你的DAO
抽象在保存之前转换您的 POJO,反之亦然。
P.S:如果您对具有如此多单个变量的如此复杂的 Schema 没有任何用处 classes 我真的建议您定义自定义 GSON serializer
/deserializer
从头开始将复杂的POJO转化为简化的POJO;从您的代码库中完全删除这样一个复杂的模式。
所以经过一些研究,我找到了一个注释,如果你有多个内部 classes 空间,它会处理它,你不必为它创建任何 TypeConverters。
@Embedded 可以用作实体或 Pojo 字段上的注释,以表示嵌套字段(即注释字段的 class) 可以在 SQL 查询中直接引用。
例如,如果您有 2 个 classes:
public class Coordinates {
double latitude;
double longitude;
}
public class Address {
String street;
@Embedded
Coordinates coordinates;
}
在将 SQLite 行映射到地址时,Room 会将纬度和经度视为地址 class 的字段。
我有多个 POJO classes 作为主 POJO class 的类型,我用它来使用 Retrofit 解析 json 数据。所以我为第一级 Pojo 提供了类型转换器,但我在读取存储的数据时遇到了问题,因为它的格式不正确。
这是我的 POJO class
@Entity(tableName = "entry")
public class Entry implements Parcelable {
@NonNull
@PrimaryKey
@SerializedName("id")
private FeedID feedId;
@SerializedName("title")
private Title EntryTitle;
@SerializedName("im:image")
private List<Image> image;
@SerializedName("summary")
private Summary summary;
public Entry(){}
public FeedID getFeedId() {
return feedId;
}
public void setFeedId(FeedID feedId) {
this.feedId = feedId;
}
public Title getEntryTitle() {
return EntryTitle;
}
public void setEntryTitle(Title entryTitle) {
this.EntryTitle = entryTitle;
}
public List<Image> getImage() {
return image;
}
public void setImage(List<Image> image) {
this.image = image;
}
public Summary getSummary() {
return summary;
}
public void setSummary(Summary summary) {
this.summary = summary;
}
@SuppressWarnings("unused")
public static final Parcelable.Creator<Entry> CREATOR = new Parcelable.Creator<Entry>() {
@Override
public Entry createFromParcel(Parcel in) {
return new Entry(in);
}
@Override
public Entry[] newArray(int size) {
return new Entry[size];
}
};
protected Entry(Parcel in) {
feedId = (FeedID) in.readValue(FeedID.class.getClassLoader());
EntryTitle = (Title) in.readValue(Title.class.getClassLoader());
if (in.readByte() == 0x01) {
image = new ArrayList<Image>();
in.readList(image, Image.class.getClassLoader());
} else {
image = null;
}
summary = (Summary) in.readValue(Summary.class.getClassLoader());
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeValue(feedId);
dest.writeValue(EntryTitle);
if (image == null) {
dest.writeByte((byte) (0x00));
} else {
dest.writeByte((byte) (0x01));
dest.writeList(image);
}
dest.writeValue(summary);
}
public class Title implements Parcelable {
private String label;
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
@SuppressWarnings("unused")
public final Parcelable.Creator<Title> CREATOR = new Parcelable.Creator<Title>() {
@Override
public Title createFromParcel(Parcel in) {
return new Title(in);
}
@Override
public Title[] newArray(int size) {
return new Title[size];
}
};
protected Title(Parcel in) {
label = in.readString();
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(label);
}
}
public class Image implements Parcelable {
private String label;
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
@SuppressWarnings("unused")
public final Parcelable.Creator<Image> CREATOR = new Parcelable.Creator<Image>() {
@Override
public Image createFromParcel(Parcel in) {
return new Image(in);
}
@Override
public Image[] newArray(int size) {
return new Image[size];
}
};
protected Image(Parcel in) {
label = in.readString();
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(label);
}
}
public class Summary implements Parcelable {
private String label;
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
@SuppressWarnings("unused")
public final Parcelable.Creator<Summary> CREATOR = new Parcelable.Creator<Summary>() {
@Override
public Summary createFromParcel(Parcel in) {
return new Summary(in);
}
@Override
public Summary[] newArray(int size) {
return new Summary[size];
}
};
protected Summary(Parcel in) {
label = in.readString();
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(label);
}
}
public class FeedID implements Parcelable {
private Attributes attributes;
public Attributes getAttributes() {
return attributes;
}
public void setAttributes(Attributes attributes) {
this.attributes = attributes;
}
@SuppressWarnings("unused")
public final Parcelable.Creator<FeedID> CREATOR = new Parcelable.Creator<FeedID>() {
@Override
public FeedID createFromParcel(Parcel in) {
return new FeedID(in);
}
@Override
public FeedID[] newArray(int size) {
return new FeedID[size];
}
};
protected FeedID(Parcel in) {
attributes = (Attributes) in.readValue(Attributes.class.getClassLoader());
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeValue(attributes);
}
}
public class Attributes implements Parcelable {
@SerializedName("im:id")
private String id;
public String getIm() {
return id;
}
public void setIm(String im) {
this.id = im;
}
@SuppressWarnings("unused")
public final Parcelable.Creator<Attributes> CREATOR = new Parcelable.Creator<Attributes>() {
@Override
public Attributes createFromParcel(Parcel in) {
return new Attributes(in);
}
@Override
public Attributes[] newArray(int size) {
return new Attributes[size];
}
};
protected Attributes(Parcel in) {
id = in.readString();
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(id);
}
}
}
这是我的 TypeConverter class
public class RoomTypeConverters {
@TypeConverter
public static String toString(Entry.Title value) {
Gson gson = new Gson();
String json = gson.toJson(value);
return json;
}
@TypeConverter
public static Entry.Title toTitle(String value) {
Type listType = new TypeToken<Entry.Title>() {
}.getType();
return new Gson().fromJson(value, listType);
}
@TypeConverter
public static String toString(Entry.FeedID value) {
Gson gson = new Gson();
String json = gson.toJson(value);
return json;
}
@TypeConverter
public static Entry.FeedID toFeedID(String value) {
Type listType = new TypeToken<Entry.FeedID>() {
}.getType();
return new Gson().fromJson(value, listType);
}
@TypeConverter
public static String toString(Entry.Summary value) {
Gson gson = new Gson();
String json = gson.toJson(value);
return json;
}
@TypeConverter
public static Entry.Summary toSummary(String value) {
Type listType = new TypeToken<Entry.Summary>() {
}.getType();
return new Gson().fromJson(value, listType);
}
@TypeConverter
public static String toString(List<Entry.Image> value) {
Gson gson = new Gson();
String json = gson.toJson(value);
return json;
}
@TypeConverter
public static List<Entry.Image> toImage(String value) {
Type listType = new TypeToken<Entry.Summary>() {
}.getType();
return new Gson().fromJson(value, listType);
}
}
我是否必须只为一个字段创建多个这样的 POJO?我们还有其他选择吗?
是的,要保存 POJO,您必须 为其定义 class(内部或正常 class)。
但是我从你的数据模式中了解到你有一个可能 复杂的 数据存储服务器端并且你想使用 子集 在你的应用程序中的数据。您的 POJO 可以简化,因此您可以创建一个名为 EntryRecord
的 Class,并为其定义一个简单的 setter 和 getter,如下所示:
@Entity(tableName = "entry")
public class EntryRecord {
@NonNull
@PrimaryKey
@SerializedName("id")
private String feedId;
@SerializedName("title")
private StringEntryTitle;
@SerializedName("im:image")
private String[] image;
@SerializedName("summary")
private String summary;
public EntryRecord(Entry entry){
//Resolve primitive values from Entry class attributes..
}
public Entry getEntry(){
Entry entry = new Entry();
//Resolve entry values from primitive ones...
return entry ;
}
}
,现在你所要做的就是使用这个class来保存和恢复你的数据,你甚至可以让你的DAO
抽象在保存之前转换您的 POJO,反之亦然。
P.S:如果您对具有如此多单个变量的如此复杂的 Schema 没有任何用处 classes 我真的建议您定义自定义 GSON serializer
/deserializer
从头开始将复杂的POJO转化为简化的POJO;从您的代码库中完全删除这样一个复杂的模式。
所以经过一些研究,我找到了一个注释,如果你有多个内部 classes 空间,它会处理它,你不必为它创建任何 TypeConverters。
@Embedded 可以用作实体或 Pojo 字段上的注释,以表示嵌套字段(即注释字段的 class) 可以在 SQL 查询中直接引用。
例如,如果您有 2 个 classes:
public class Coordinates {
double latitude;
double longitude;
}
public class Address {
String street;
@Embedded
Coordinates coordinates;
}
在将 SQLite 行映射到地址时,Room 会将纬度和经度视为地址 class 的字段。