问题描述
如何在 android sqlite 数据库中存储具有其他对象作为实例变量的对象。
基本上,我的 Rest Api 调用的 JSON 响应如下所示:
{
"announcements": [
{
"courseId": "196014605914","id": "269865109791","text": "Ignore the prevIoUs link. Join the already started CHM 112","state": "PUBLISHED","alternateLink": "https://classroom.google.com/c/MTk2MDE0NjA1OTE0/p/MjY5ODY1MTA5Nzkx","creationTime": "2021-02-08T09:18:05.420Z","updateTime": "2021-02-08T09:18:05.415Z","creatorUserId": "101562079220031604157"
},{
"courseId": "196014605914","id": "246419265642","text": "Note2","materials": [
{
"driveFile": {
"driveFile": {
"id": "1CjL0RV7PdcIrrRWii1ApUown3YoyEKTx","title": "HYDROCARBONS2-C-C,C=C AND ALKYnes.pdf","alternateLink": "https://drive.google.com/open?id=1CjL0RV7PdcIrrRWii1ApUown3YoyEKTx","thumbnailUrl": "https://drive.google.com/thumbnail?id=1CjL0RV7PdcIrrRWii1ApUown3YoyEKTx&sz=s200"
},"shareMode": "VIEW"
}
}
],"alternateLink": "https://classroom.google.com/c/MTk2MDE0NjA1OTE0/p/MjQ2NDE5MjY1NjQy","creationTime": "2021-01-25T10:41:45.094Z","updateTime": "2021-01-25T10:41:44.260Z",],"nextPagetoken": "GkUSQxJBCLHA5Pr4LhI4Cg5iDAi2pfD_BRDAoOKzAQoOYgwItqXw_wUQgMCNtwEKCgiAgICg29jhsFoKCgiAgIDgwu223Hk"
}
这是公告对象的一部分,但有些没有材质对象,如上所示。问题是并不是所有的公告都有 Material 对象,所以一个公告对象最多可以有 20 个材质对象。
我的数据模型如下所示:
public class CourseDetailsItem{
private final String message;
private final Long time;
private final String author;
private final List<Material> materials;
//... Appropriate getters and setters
//Material.java
public class Material{
private final String label;
private final String link;
//... Appropriate getters and setters
存储对象以供离线使用的最佳方式是什么?
在我的 DbHelper 类中,我很困惑
sqliteDatabase db = this.getWritableDatabase();
String CREATE_COURSE_TABLE = "CREATE TABLE IF NOT EXISTS _"+courseId+" ("+ ID +" INTEGER PRIMARY KEY," + MESSAGE + " TEXT,"+ TIME + " INTEGER," + AUTHOR + " TEXT," + LABEL + " TEXT," + LINK + " TEXT"+")";
db.execsql(CREATE_COURSE_TABLE);
ContentValues values = new ContentValues();
values.put(MESSAGE,courseDetailsItem.getMessage());
values.put(TIME,courseDetailsItem.getTime());
values.put(AUTHOR,courseDetailsItem.getAuthor());
//values.put(); HERE HOW DO I STORE MATERIAL OBJECT
//Considering the fact that Material Object Could be upto Twenty for each of my entry
请大家...
这里请不要负能量,我只是想不出这里的解决方案
解决方法
最好的或最直观的方法是在关系 SQLite 数据库中也反映它们的关系。
这意味着您将有一个 Announcement
表和一个 Material
表。
在 Material
表中,您需要添加一个“外键”,其中包含它所指的 Announcement
的主 ID。这样您就可以为一个 Material
存储 0...n 个 Announcement
。您的 Announcement
模型/表不需要更改,可以保持原样。
注意:据我所知,SQLite 不支持真正的“外键”定义。这还不错,因为它只是关于基于主键从一个表到另一个表的“指针”的概念。在真实的、成熟的数据库中,它将评估它并确保基于它的数据完整性。这种严格性并不总是需要或想要的,因此在 SQLite 中不受支持 - 使其更轻量级。您还可以通过正确编写的代码确保相同的数据完整性。
那么您将有两个如下所示的表格:
公告(courseId、id、text、...)
材料(announcementId、id、title、alternateLink、...)
编辑:这也称为 OneToMany
关系。当您寻找“在关系数据库中对 OneToMany 关系建模”时,您会发现很多资源对其进行了更详细的解释。
在存储 Announcement
时,您还将“简单地”将 Material
对象存储在它们的表中。在这里,您可以评估是否要保持强大的数据完整性并希望在单个事务中存储所有 Announcement
和 Material
对象,或者是否不需要如此严格并且您将存储它在不同的交易中。
有几种可能:
- 单个
Announcement
对象与其所有Material
对象一起存储在一个事务中 - 所有
Announcement
对象与所有Material
一起存储在一个事务中 - 所有
Announcement
对象存储在一个事务中,然后所有Material
对象存储在一个事务中
第一个选项是逻辑上偏爱并提供最佳用户体验。
从数据库加载 Announcement
时,您可以决定是要加载 Material
的列表 eagerly 还是 lazy。查询应如下所示:
SELECT * FROM Material WHERE announcementId = this.id
。
它会返回与个人 Material
相关联的 Announcement
列表。