任何人都对如何使用SQLite实现ContentProvider的一对多映射有很好的建议?如果查看Uri ContentProvider#insert(Uri, ContentValues),您会发现它具有ContentValues参数,其中包含要插入的数据。问题在于,在其当前实现中ContentValues不支持put(String, Object)方法,并且类是最终的,因此我无法对其进行扩展。为什么有问题?这是我的设计:

我有2个处于一对多关系的表。为了用代码表示这些,我有2个模型对象。第一个代表主记录,并具有一个字段,该字段是第二个对象实例的列表。现在,我在模型对象#1中有一个辅助方法,该方法返回从当前对象生成的ContentValues。用ContentValues#put重载的方法填充原始字段很简单,但是我对这个列表不满意。因此,当前由于我的第二个表行只是一个String值,因此生成了一个逗号分隔的String,然后将其解析为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 */}

这是ContentProvider#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();
    }

}

最佳答案

我认为您正在寻找一对多关系的错误结局。

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

如果您有一个没有内容提供程序的纯SQLite数据库,则将执行相同的操作。关系数据库中的一对多关系是通过在“许多”侧的表上进行插入/更新/删除来实现的,每个插入/更新/删除都具有返回“一个”侧的外键。

现在,从面向对象的角度来看,这是不理想的。欢迎您创建ORM样式的包装器对象(例如Hibernate),该对象可让您从“一个”侧操纵一组子代。然后,一个足够智能的集合类可以转过来并同步“许多”表以进行匹配。但是,正确实现这些不一定很琐碎。

关于Android:SQLite一对多设计,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/2205327/

10-12 01:38