Android:SQLite一对多devise

任何人都有很好的build议,如何使用ContentProvider实现一对多SQLite映射? 如果您查看Uri ContentProvider#insert(Uri, ContentValues)您可以看到它具有包含要插入的数据的ContentValues参数。 问题是在它的当前实现ContentValues不支持put(String, Object)方法,并且类是final的,所以我不能扩展它。 为什么这是一个问题? 这是我的devise:

我有2个表是一对多的关系。 为了在代码中表示这些,我有2个模型对象。 1st表示主logging,并且具有第二个对象实例列表的字段。 现在,我在模型对象#1中有一个帮助器方法,它返回当前对象生成的ContentValues 。 用ContentValues#put填充一个原始字段是很简单的, ContentValues#put重载的方法ContentValues#put去,但是我对列表ContentValues#put好运。 所以目前,因为我的第二个表行只是一个单一的string值,我生成一个逗号分隔的string,然后我重新parsing为ContentProvider#insert内的String []。 这感觉很糟糕,所以也许有人可以提示如何以清洁的方式来完成。

这是一些代码。 首先从示范课开始:

 public ContentValues toContentValues() { ContentValues values = new ContentValues(); values.put(ITEM_ID, itemId); values.put(NAME, name); values.put(TYPES, concat(types)); return values; } private String concat(String[] values) { /* trivial */} 

这里是减lessContentProvider#insert方法的版本

 public Uri insert(Uri uri, ContentValues values) { SQLiteDatabase db = dbHelper.getWritableDatabase(); db.beginTransaction(); try { // populate types String[] types = ((String)values.get(Offer.TYPES)).split("|"); // we no longer need it values.remove(Offer.TYPES); // first insert row into OFFERS final long rowId = db.insert("offers", Offer.NAME, values); if (rowId > 0 && types != null) { // now insert all types for the row for (String t : types) { ContentValues type = new ContentValues(8); type.put(Offer.OFFER_ID, rowId); type.put(Offer.TYPE, t); // insert values into second table db.insert("types", Offer.TYPE, type); } } db.setTransactionSuccessful(); return ContentUris.withAppendedId(Offer.CONTENT_URI, rowId); } catch (Exception e) { Log.e(TAG, "Failed to insert record", e); } finally { db.endTransaction(); } } 

Solutions Collecting From Web of "Android:SQLite一对多devise"

我想你是在看一对多关系的错误结局。

例如,查看ContactsContract内容提供者。 联系人可以有许多电子邮件地址,许多电话号码等。完成的方式是通过在“多”一边进行插入/更新/删除。 要添加新的电话号码,请插入一个新的电话号码,提供电话号码所属联系人的ID。

如果你有一个没有内容提供者的纯SQLite数据库,你也可以这样做。 关系数据库中的一对多关系是通过在“多”一侧的表上插入/更新/删除来实现的,每个关系数据库都有一个外键返回到“一”侧。

现在,从面向对象的angular度来看,这并不理想。 欢迎您创buildORM样式的包装器对象(认为Hibernate),允许您从“一个”方面操作一组子对象。 一个足够智能的集合类可以转向并同步“多”表来匹配。 但是,这些并不一定是微不足道的。

您可以使用ContentProviderOperations

它们基本上是批量操作,能够反向引用为父行生成的标识符。

ContentProviderOperations如何用于一对多devise,在这个答案中已经很好地解释了: withValueBackReference的语义是什么?

所以我要回答我自己的问题。 我有两个表和两个模型对象在正确的轨道上。 什么错过了什么困惑的是,我想通过一个调用通过ContentProvider#insert直接插入复杂的数据。 这是错误的。 ContentProvider应该创build并维护这两个表,但决定使用哪个表应由ContentProvider#insert Uri参数决定。 使用ContentResolver并向模型对象添加诸如“addFoo”之类的方法非常方便。 这样的方法将采取ContentResolver参数,并在这里最后是插入一个复杂的logging的序列:

  1. 通过ContentProvider#insert插入父logging并获取loggingID
  2. 每个孩子提供父母ID(foregn键),并使用ContentProvider#insert不同的Uri插入子logging

所以剩下的唯一问题是如何在交易中包含上述代码?