具有复杂 Json 结构的 Room

2024-04-04

我是 Room 的新手,目前正在做我的一个项目,我应该在其中插入一些改造的 GSON 数据。首先,让我在下面展示我的 JSON,它将提供清晰的结构。

{
"organization": {
    "id": 0,
    "title": "string",
    "description": "HTML String",
    "style": {
        "navigationBackgroundColor": "#cd1325",
        "navigationTextColor": "#ffffff",
        "topBarLabel": "27July2015abcd",
        "topBarBackgroundColor": "#cd1325",
        "topBarTextColor": "#ffffff",
        "bodyBackgroundColor": "#f5c233",
        "bodyTextColor": "#646363",
        "bannerBackgroundColor": "#ffffff",
        "bannerTextColor": "#000000",
        "buttonBackgroundColor": "#000000",
        "buttonTextColor": "#ffffff",
        "baseTextSize": 0,
        "htmlWrapper": "string"
    }
    "login_options": [{
            "name": "string",
            "title": "EMAIL",
            "description": "string",
            "state": "string",
            "allowed_email_domain": "string",
            "restricted_email_domain": "string"
        }, {
            "name": "string",
            "titl"e: "GOOGLE",
            "description": "string",
            "url": "string",
            "clientId": "string",
            "clientSecret": "string",
            "redirectUri": "string",
            "state": "string",
            "nonce": "string",
            "authorizationEndpointUri": "string",
            "tokenEndpointUri": "string"
        }
    ]
}

}

我正在通过改造来解析这个问题,效果很好。以下是创建的模型类名称https://www.jsonschema2pojo.org/ https://www.jsonschema2pojo.org/

好的。现在我必须通过我的存储库将它们插入 Room 数据库,为此我面临很多困难。任何人都可以帮助我如何创建实体以及如何将这些数据模型插入​​房间。仍然不确定是否将 GSON 模型插入 Room 或创建实体并将解析数据放入其中然后插入。 到目前为止我已经尝试过了。

登录选项表

@Parcelize
@Entity
public class LoginOptionsTable {

@ColumnInfo
@PrimaryKey(autoGenerate = true)
public long loginOpnId;

@ColumnInfo(name = "login_options_name")
public String name;

@ColumnInfo(name = "login_options_title")
public String title;

@ColumnInfo(name = "login_options_description")
public String description;

@ColumnInfo
public String state;

@ColumnInfo
public String allowedEmailDomain;

@ColumnInfo
public String restrictedEmailDomain;

@ColumnInfo
public String url;

@ColumnInfo
public String clientId;

@ColumnInfo
public String clientSecret;

@ColumnInfo
public String redirectUri;

@ColumnInfo
public String nonce;

@ColumnInfo
public String authorizationEndpointUri;

@ColumnInfo
public String tokenEndpointUri;

public static List<LoginOptionsTable> fromObject(List<LoginOption> 
mOptions){

    List<LoginOptionsTable> groups = new ArrayList<>();

    for(int i=0; i<mOptions.size(); i++){
        LoginOptionsTable st = new LoginOptionsTable();

        st.name = mOptions.get(i).getName();
        st.title = mOptions.get(i).getTitle();
        st.description = mOptions.get(i).getDescription();
        st.state = mOptions.get(i).getState();
        st.allowedEmailDomain = mOptions.get(i).getAllowedEmailDomain();
        st.restrictedEmailDomain = 
        mOptions.get(i).getRestrictedEmailDomain();
        st.url = mOptions.get(i).getUrl();
        st.clientId = mOptions.get(i).getClientId();
        st.clientSecret = mOptions.get(i).getClientSecret();
        st.redirectUri = mOptions.get(i).getRedirectUri();
        st.nonce = mOptions.get(i).getNonce();
        st.authorizationEndpointUri = 
        mOptions.get(i).getAuthorizationEndpointUri();
        st.tokenEndpointUri = mOptions.get(i).getTokenEndpointUri();

        groups.add(st);
    }


    return groups;
}

}

样式实体:

@Parcelize
@Entity
public class StyleTable {

@ColumnInfo
@PrimaryKey(autoGenerate = true)
public long styleId;

@ColumnInfo
public String navigationBackgroundColor;
@ColumnInfo
public String navigationTextColor;
@ColumnInfo
public String topBarLabel;
@ColumnInfo
public String topBarBackgroundColor;
@ColumnInfo
public String topBarTextColor;
@ColumnInfo
public String bodyBackgroundColor;
@ColumnInfo
public String bodyTextColor;
@ColumnInfo
public String bannerBackgroundColor;
@ColumnInfo
public String bannerTextColor;
@ColumnInfo
public String buttonBackgroundColor;
@ColumnInfo
public String buttonTextColor;
@ColumnInfo
public Integer baseTextSize;
@ColumnInfo
public String htmlWrapper;


public static StyleTable fromObject(Style mStyle) {
    StyleTable st = new StyleTable();

    st.navigationBackgroundColor = mStyle.getNavigationBackgroundColor();
    st.navigationTextColor = mStyle.getNavigationTextColor();
    st.topBarLabel = mStyle.getTopBarLabel();
    st.topBarBackgroundColor = mStyle.getTopBarBackgroundColor();
    st.topBarTextColor = mStyle.getTopBarTextColor();
    st.bannerBackgroundColor = mStyle.getBodyBackgroundColor();
    st.bannerTextColor = mStyle.getBannerTextColor();
    st.buttonBackgroundColor = mStyle.getButtonBackgroundColor();
    st.buttonTextColor = mStyle.getButtonTextColor();
    st.baseTextSize = mStyle.getBaseTextSize();
    st.htmlWrapper = mStyle.getHtmlWrapper();

    return st;
}

}

组织实体:

@Parcelize
@Entity(foreignKeys = {@ForeignKey(entity = StyleTable.class, parentColumns = 
"styleId", childColumns = "stId"),
    @ForeignKey(entity = LoginOptionsTable.class, parentColumns = 
"loginOptionId", childColumns = "loginOpnId")
})
public class OrgTable {

@ColumnInfo
@PrimaryKey
public long id;

@ColumnInfo
public String title;

@ColumnInfo
public String description;

@ColumnInfo
public long stId;

//TODo make it for mutiple table
@ColumnInfo
public Long loginOptionsId;

@Ignore
public StyleTable style;

@Ignore
public List<LoginOptionsTable> loginOptions = null;

public static OrgTable fromObject(Organization organization){
    OrgTable org = new OrgTable();
    org.id = organization.getId();
    org.title = organization.getTitle();
    org.description = organization.getDescription();
    StyleTable st = StyleTable.fromObject(organization.getStyle());
    org.style = st;
    //make the relation through Id
    org.stId = st.styleId;

    List<LoginOptionsTable> lo = 
   LoginOptionsTable.fromObject(organization.getLoginOptions());
    org.loginOptions = lo;
    //make the relation through Id
    org.loginOptionsId = lo.get(0).loginOpnId;


return org;
}

}

DAO

@Dao
public interface OrgDAO {

@Query("SELECT * FROM OrgTable")
OrgTable getOrganization();

@Insert
void insertOrg(OrgTable org);

}

我尝试创建这些,但无法理解如何保持它们之间的关系以及插入/获取保存的数据。


我尝试创建这些,但无法理解如何保持它们之间的关系以及插入/获取保存的数据。

您可以通过两种方式执行此操作:

  • 包含所有三个表的 POJO@Embedded(仅适用于 1 个组织 -> 1 个登录名和 1 个样式)

  • 带有 POJO 和 OrgTable@Embedded并使用 LoginOptionsTable 和 StyleTable@Relation注释

第一个示例(所有三个表@Embedded) 存在 :-

class OrgWithLoginAndStyle {

    /* Note use Query that
        JOINS the Orgtable with the Login table
        and JOINS the Orgtable with the Style table
     */

    @Embedded
    OrgTable orgTable;
    @Embedded
    LoginOptionsTable loginOptionsTable;
    @Embedded
    StyleTable styleTable;

}

利用这一点的 Dao 的一个例子是:-

@Query("SELECT * FROM OrgTable " +
        "JOIN StyleTable ON StyleTable.styleId = OrgTable.stId " +
        "JOIN LoginOptionsTable ON LoginOptionsTable.loginOpnId = OrgTable.loginOptionsId")
List<OrgWithLoginAndStyle> getOrganizationLoginAndStyle();
  • 这是更灵活的查询方式,因为所有列都可用于 WHERE 子句等,但查询更复杂。

第二个的例子(与@RelationLoginOptionsTable 和 StyleTable 的注释):-

class OrganizationWithLoginOptionsAndWithStyles {

    @Embedded
    OrgTable orgTable;
    @Relation(entity = LoginOptionsTable.class,parentColumn = "loginOptionsId",entityColumn = "loginOpnId")
    List<LoginOptionsTable> loginOptionsTables;
    @Relation(entity = StyleTable.class,parentColumn = "stId",entityColumn = "styleId")
    List<StyleTable> styleTables;
}
  • 这也许更容易编码。然而,它的效率较低,因为样式和 LoginOptions 是为每个 OrgTable 独立检索的。因此,查询更简单,因为您只需要获取 OrgTable。 Room 负责构建相关对象的工作。查询仅限于 OrgTable 列上的 WHERE 等(如果您 JOINed 其他表,此类子句可能不会获得所需的结果(在您的情况下可能没问题,因为每个 OrgTable 对象只有 1 个 LoginOptions 和 1 个 Style))

利用这一点的 Dao 的一个例子是:-

@Transaction
@Query("SELECT * FROM OrgTable")
List<OrganizationWithLoginOptionsAndWithStyles> getOrganizationsLoginsAndStyles();
  • 请注意,建议使用 @Transaction,因为(我相信)正在运行底层查询来获取 LoginOptionsTable 对象和 StyleTable 对象。

Note关于你的getOrganization查询(见评论)

@Query("SELECT * FROM OrgTable")
//OrgTable getOrganization(); /* <<<<<<<<<< WRONG should be a List */
List<OrgTable> getOrganizations();

和你的insertOrg

@Insert
//void insertOrg(OrgTable org)
long insertOrg(OrgTable org); /* <<<<<<<<<< might as well allow the id of the inserted row to be obtained */

好的。现在我必须通过我的存储库将它们插入 Room 数据库,为此我面临很多困难。

我相信您的 OrgTable FK 定义应该如下:-

@Entity(foreignKeys = {@ForeignKey(entity = StyleTable.class, parentColumns =
        "styleId", childColumns = "stId"),
        @ForeignKey(entity = LoginOptionsTable.class, parentColumns =
                "loginOpnId", childColumns = "loginOptionsId")
})
  • 即 LoginOptions 子级和父级是错误的,并且父级应该是 loginOptionsId 而不是 loginOptionId (不是 Option 之后的 s)。

基础测试

使用上面的以下代码,除了使OrgDao班级 :-

@Dao
public interface OrgDAO {

    @Query("SELECT * FROM OrgTable")
    //OrgTable getOrganization(); /* <<<<<<<<<< WRONG should be a List */
    List<OrgTable> getOrganizations();

    @Query("SELECT * FROM OrgTable " +
            "JOIN StyleTable ON StyleTable.styleId = OrgTable.stId " +
            "JOIN LoginOptionsTable ON LoginOptionsTable.loginOpnId = OrgTable.loginOptionsId")
    List<OrgWithLoginAndStyle> getOrganizationLoginAndStyle();

    @Transaction
    @Query("SELECT * FROM OrgTable")
    List<OrganizationWithLoginOptionsAndWithStyles> getOrganizationsLoginsAndStyles();

    @Insert
    //void insertOrg(OrgTable org)
    long insertOrg(OrgTable org); /* <<<<<<<<<< might as well allow the id of the inserted row to be obtained */

    @Insert
    long insertStyle(StyleTable styleTable);

    @Insert
    long insertLoginOptions(LoginOptionsTable loginOptionsTable);
}

并使用:-

@Database(entities = {OrgTable.class,StyleTable.class,LoginOptionsTable.class},version = 1) 抽象类 OrgLoginStyleDatabase 扩展 RoomDatabase { 抽象 OrgDAO getOrgDao(); }

并通过一个活动(请注意,您的一些代码已被注释掉,即实体的 @Parcelize 和 @Ignored Concstructors 的使用):-

public class MainActivity extends AppCompatActivity {

    OrgLoginStyleDatabase db;
    OrgDAO dao;
    public static final String TAG = "OLSINFO";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        db = Room.databaseBuilder(this,OrgLoginStyleDatabase.class,"orgloginoptionsstyle.db")
                .allowMainThreadQueries()
                .build();
        dao = db.getOrgDao();

        StyleTable s1 = new StyleTable();
        s1.bannerBackgroundColor = "X";
        s1.bannerTextColor = "X";
        s1.baseTextSize = 20;
        s1.bodyBackgroundColor = "X";
        s1.bodyTextColor = "X";
        s1.buttonBackgroundColor = "X";
        s1.buttonTextColor = "X";
        s1.htmlWrapper = "X";
        s1.navigationBackgroundColor = "X";
        s1.navigationTextColor = "X";
        s1.styleId = 100;
        s1.topBarBackgroundColor = "X";
        s1.topBarLabel = "X";
        s1.topBarTextColor = "X";
        long s1Id = dao.insertStyle(s1);
        LoginOptionsTable l1 = new LoginOptionsTable();
        l1.allowedEmailDomain = "Y";
        l1.authorizationEndpointUri = "Y";
        l1.clientId = "Y";
        l1.clientSecret = "Y";
        l1.description = "Y";
        l1.loginOpnId = 1000;
        l1.name = "Y";
        l1.nonce = "Y";
        l1.redirectUri = "Y";
        l1.restrictedEmailDomain = "Y";
        l1.state = "Y";
        l1.title = "Y";
        l1.url = "Y";
        long l1Id = dao.insertLoginOptions(l1);
        OrgTable o1 = new OrgTable();
        o1.description = "Z";
        o1.id = 10000;
        o1.loginOptionsId = l1Id;
        o1.stId = s1Id;
        dao.insertOrg(o1);
        List<OrgTable> orgTableList = dao.getOrganizations();
        for(OrgTable o: orgTableList) {
            logOrgTable(o,"FROM getOrganizations -> ");
        }
        List<OrganizationWithLoginOptionsAndWithStyles> organizationsLoginsAndStylesList = dao.getOrganizationsLoginsAndStyles();
        for(OrganizationWithLoginOptionsAndWithStyles owloaws: organizationsLoginsAndStylesList) {
            logOrgTable(owloaws.orgTable,"FROM (@Relations) getOrganizationsLoginsAndStyles -> ");
            for(LoginOptionsTable lot: owloaws.loginOptionsTables) {
                logLoginOptionsTable(lot,"\t");
            }
            for(StyleTable s: owloaws.styleTables) {
                logStyleTable(s,"\t");
            }
        }
        List<OrgWithLoginAndStyle> owlas = dao.getOrganizationLoginAndStyle();
        for(OrgWithLoginAndStyle o: owlas) {
            logOrgTable(o.orgTable,"FROM (@Embeddeds) getOrganizationLoginAndStyle -> ");
            logLoginOptionsTable(o.loginOptionsTable,"\t");
            logStyleTable(o.styleTable,"\t");
        }
    }

    private void logOrgTable(OrgTable o,String preamble) {
        Log.d(TAG,preamble + "OrgTable Description = " + o.description + " ID = " + o.id);
    }
    private void logStyleTable(StyleTable s, String preamble) {
        Log.d(TAG,preamble + "StyleTable Description = " + s.topBarTextColor + " ID =" + s.styleId);
    }
    private void logLoginOptionsTable(LoginOptionsTable l, String preamble) {
        Log.d(TAG,preamble + "LoginOptionsTable Description = " + l.description + " ID = " + l.loginOpnId);
    }
}

Result

运行时(仅运行一次,因为已使用硬编码 ID),输出到日志的结果是:-

2021-04-12 21:51:50.981 D/OLSINFO: FROM getOrganizations -> OrgTable Description = Z ID = 10000

2021-04-12 21:51:50.987 D/OLSINFO: FROM (@Relations) getOrganizationsLoginsAndStyles -> OrgTable Description = Z ID = 10000
2021-04-12 21:51:50.987 D/OLSINFO:  LoginOptionsTable Description = Y ID = 1000
2021-04-12 21:51:50.987 D/OLSINFO:  StyleTable Description = X ID =100

2021-04-12 21:51:50.989 D/OLSINFO: FROM (@Embeddeds) getOrganizationLoginAndStyle -> OrgTable Description = Z ID = 10000
2021-04-12 21:51:50.989 D/OLSINFO:  LoginOptionsTable Description = Y ID = 1000
2021-04-12 21:51:50.989 D/OLSINFO:  StyleTable Description = X ID =100
  • 所有三个对象均已成功插入,并且所有三个查询均按预期工作。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

具有复杂 Json 结构的 Room 的相关文章

  • 您的手机中未安装应用程序

    我在模拟器中运行该应用程序 它成功运行 并且应用程序的图标显示在模拟器菜单中 但是当我尝试从模拟器菜单再次运行该应用程序时 它不允许我从中运行并显示 Toast 您的手机中未安装应用程序 在图像中 红色圆形是我的应用程序图标 如果您有您的M
  • FCM:无法实例化接收器 com.google.firebase.iid.FirebaseInstanceIdReceiver:

    仅在 Oreo 8 0 中接收推送通知时应用程序崩溃 java lang RuntimeException Unable to instantiate receiver com google firebase iid FirebaseIns
  • Moshi 无法解析 nullable

    你好 希望你能帮助我 使用 kotlin Retrofit2 moshi 我从 https api spacexdata com v3 launches 获取数据并解析它 一切都很顺利 我得到的属性如下 flight number miss
  • Mediaplayer 播放几次后停止播放

    我有一个按钮 按下它会播放一个随机声音剪辑 然后播放另一个声音剪辑 然后通过一个媒体播放器播放另一个声音剪辑 但是多次按下该按钮 15 20 次 后 所有音频都会停止 我在播放最后一个音频剪辑后释放媒体播放器 所以我不认为这是原因 有什么指
  • 错误:链接引用失败。 -> 排队作业

    我正在使用 Kotlin 学习 Android Material Design 一切都很顺利 直到我尝试使用 android support design widget FloatingActionButton 当我重建项目时 我收到以下错
  • 将网页保存到android中的webview缓存中

    我正在创建一个应用程序 它将从互联网下载一些网页 并在用户单击按钮时将它们保存到缓存 并在没有互联网可用时加载它们 当我运行代码时 出现空指针异常 我已在清单文件中添加了所有必要的权限 public class MainActivity e
  • 我从 String placeName = placeText.getText().toString(); 收到空指针异常

    您好 想从编辑文本中获取地名并在地图上标记 这是我的代码 其中出现空指针异常 请帮助我应该做什么以及哪里出错了 因为我从对话框中的编辑文本字段获取地名 View layout View inflate this R layout alert
  • 每当调用 startactivityforresult 时 Android 就会终止我的应用程序

    好吧 在我的应用程序中 我使用 Android 的默认相机和图库 startActivityforResult 为 Intent i new Intent android intent action PICK MediaStore Imag
  • 如何使用 queryIntentActivityOptions() 方法

    我正在尝试创建一个对话框 显示用户手机中的所有应用程序 可用于从存储中选择照片或使用相机拍摄照片 以下是我计划使用的两个意图 Intent photoPickerIntent new Intent Intent ACTION PICK ph
  • 为什么抽屉布局中的视图强制缩放以填充屏幕

    这是我的测试代码
  • 如何在android 4.2中显示选项菜单

    我正在尝试在我的测试应用程序中创建菜单选项 当我将清单中的主题设置为默认时 我可以看到菜单 菜单显示在顶部 如果我将清单中的主题设置为 NoTitleBar 我看不到菜单选项 我想在清单中设置主题 NoTitleBar 时获取菜单 如何修复
  • 使用 Spotify SDK 安装 Android 应用程序时出错,[INSTALL_FAILED_NO_MATCHING_ABIS]

    我正在尝试遵循Spotify Beta SDK 使用教程 https developer spotify com technologies spotify android sdk tutorial 每当我尝试将应用程序安装到 Nexus 6
  • 如何以编程方式启用小米应用程序的自动启动

    我想知道小米是否可以提供任何应用程序的后台服务 我的应用程序中有需要始终在后台运行的服务 在除小米之外的所有设备中都工作正常 如何以编程方式完成 也适用于小米 oppo vivo 和 oneplus 手机 try Intent intent
  • 如何为移动应用程序创建无密码登录

    我有兴趣在移动应用程序和 API 之间构建某种无密码登录 假设我可以控制两者 动机是必须登录对用户来说非常烦人并且存在安全风险 例如 用户将重复使用现有密码 我希望用户能够立即开始使用该应用程序 我想知道是否有一些可行的技术 例如 在移动设
  • 是否可以在本机代码中读取/编辑共享首选项?

    我有一个 Android 应用程序 其中包含一个使用 NDK 执行一些代码的 C 库 在 C 库中 我想更新应用程序共享首选项 我的问题 是否可以在本机代码中读取 编辑共享首选项 您可以在本机代码中做任何您想做的事情 这只是很麻烦 您需要
  • Android 上的 Facebook 深度链接

    我正在尝试在我的应用程序上实现 Facebook 的深度链接功能 并遇到了以下情况 我有一个名为 MainActivity 的活动 其声明如下
  • Android 处理 ListView 中的多个 EditText 字段

    只是一个基本问题 如果我有几十个 EditText 字段是 ListAdapter 的一部分 那么各个 EditText 字段如何知道它们属于哪一行 目前我正在使用 TextWatcher 来监听文本输入 我尝试扩展 TextWatcher
  • 如何获取在代码中 attrs.xml 中创建的枚举

    我创建了一个自定义视图 找到它here https bitbucket org informatic0re awesome font iconview 具有枚举类型的可声明样式属性 在 xml 中 我现在可以为我的自定义属性选择枚举条目之一
  • 如何调试仅在发布模式下崩溃的 Android 应用程序

    在调试模式下一切正常 但在发布模式下崩溃 调试模式下有哪些所需权限在发布模式下未打开 EDIT 当我将 链接 设置为 无 时 我会通过第一个屏幕进入 登录 屏幕 但是 当我添加发布权限时Internet 第一次尝试读取远程实体框架核心表时它
  • 在edittext android中插入imageview

    我想将 imageview 放在 edittext 中 可能吗 我检查了 evernote 应用程序 它能够将照片放在编辑文本部分 我想让我的应用程序完全相同 我如何才能将从图库中选择的图像视图放入编辑文本中 我首先尝试将 imagevie

随机推荐