【问题标题】:Android - How can I pass data related to two tables to a the insert method of a Content ProviderAndroid - 如何将与两个表相关的数据传递给内容提供者的插入方法
【发布时间】:2015-01-31 04:07:09
【问题描述】:

我需要插入与Order 及其对应的Detail 相关的数据。

如果没有ContentProvider,我会这样做:

public boolean insertOrder(Order order, ArrayList<OrderDetail> items) {
    boolean wasSuccessful = false;
    ContentValues cvOrder = new ContentValues();
    cvPedido.put(ORDER_CUSTOMER_ID, order.getCustomerId());
    cvPedido.put(ORDER_CUSTOMER_NAME, order.getCustomerName());     
    String insertQuery = "INSERT INTO " + ORDER_DETAIL_TABLE
            + " VALUES (?,?)";
    //...
    try {

        this.openWriteableDB();
        SQLiteStatement statement = db.compileStatement(insertQuery);
        db.beginTransaction();
        long idOrder = db.insertOrThrow(ORDER_TABLE, null, cvOrder);
        if (idOrder > 0) {


            for (int i = 0; i < items.size(); i++) {    
                OrderDetail detail=items.get(i);
                statement.clearBindings();
                statement.bindString(1, detail.getDescription);
                statement.bindDouble(2, detail.getPrice);
                //...
                statement.execute();
            }
            db.setTransactionSuccessful();
            wasSuccessful = true;               
        }

    } finally {
        db.endTransaction();
        this.closeDB();
    }
    return wasSuccessful;
}

问题是现在我想使用ContentProvider,但我不知道如何处理这种情况,即必须将有关两个或多个表的数据传递给单个 CRUD 操作,知道 @ 987654326@操作只接受两个参数:

 @Override
    public Uri insert(Uri uri, ContentValues values) {

    }

当您必须在事务中插入关系数据时,您在 ContentProvider 中做什么?

提前致谢。

【问题讨论】:

    标签: android android-sqlite android-contentprovider


    【解决方案1】:

    您应该使用ContentProviderOperation。由于它是您的ContentProvider,您可以确保applyBatch() 将执行事务中的所有操作。所有标准的内容提供者也确保是这种情况。

    请参阅我的博客 post about ContentProviderOperation 和我关于 how to use withBackReference() to access results of previous operations 的其他帖子 - 您需要访问 orderId

    一个重要的警告:一批中的所有ContentProviderOperations 必须使用相同的权限 - 但可以使用不同的 URI!在你的情况下应该没问题。

    【讨论】:

    • 对不起,我之前没有将此标记为答案,但由于我必须回到一个 IOS 项目,然后出现其他事情,直到昨天我才能回到我的android 项目并确认您的解决方案是正确的答案。
    • 没问题。感谢您牢记这一点并在这么长时间后支持我!这本身就值得获得 SO 奖。
    • 你真的应得的,因为你让我走上了正轨。再次非常感谢您,很抱歉,如果我花了这么多时间将其标记为答案,但由于我在空闲时间学习 Android,我不得不推迟这个个人项目一段时间。最后,如果有人发现它有用,这里有一个示例,说明如何在 Content Provider github.com/google/iosched/blob/master/android/src/main/java/com/… 中实现 applyBatch 方法
    【解决方案2】:

    您可以将所有数据放入 ContentValues 并拥有一个提供者。您必须对订单详细信息进行一些创意。

    在伪代码下面,我用一个整数然后是项目动态创建了一个键“DETAIL”。

               ContentValues values = new ContentValues();
                values.put(ORDER_ID,orderid);
    
               for (int i = 0; i < items.size(); i++) {    
                values.put("DETAIL" + Integer.ToString(i),items.get(i));
                }
    
                Uri uri = context.getContentResolver().insert(
                        ORDER_URI, values);
    

    然后在内容提供者中进行整理。

    @Override
    public Uri insert(Uri uri, ContentValues values) {
    
        int uriType = sURIMatcher.match(uri);
        SQLiteDatabase sqlDB = database.getWritableDatabase();
        long id = 0;
        switch (uriType) {
        case ORDER:
            // trim name and description
            trimNameDescriptions(values);
            try {
                id = sqlDB.insertOrThrow(ORDERS_TABLE,
                        null, values);
            Integer i =0;
            do (values.containsKey("DETAIL" + i.toString()){
            ContentValues v = new ContentValues();
            v.put("DETAIL",values.get("Detail" + i.toString()));
            v.put("ORDERID",id);
              //ACTUALLY CALL THE INSERT METHOD OF THE PROVIDER
            insert(DETAIL_URI,v);
             i+=1;
         }
    

    【讨论】:

    • 所以不需要交易?
    • 好吧,您可以再对其进行一些调整,然后在其中放置一笔交易。我只是展示了如何使用 ContentValues 来传递信息。如果我是您,我会使用您问题中的代码或修改订单,以便将其写入 ContentValues。
    • 谢谢@danny117。所以 ContentProviders 基本上只能同时使用一张表?
    • Idk 值得一试。我有一个视图,我严格查询提供程序中的数据,该视图使它看起来像表查询的代码,因此它更具结构化。如果有什么让代码看起来很漂亮的话。
    • @eddy:不。您可以在一个批次中处理多个表而不会出现问题。你就是不能越权。
    【解决方案3】:

    您可以设计内容提供程序来镜像您的 SQLite 表,并使用与上述相同的 insertOrder 代码。

    只需为每个表(uri)使用 insert 的内容提供者,即可执行与 insertOrder 方法中类似的操作

    另一种选择是定义您的内容提供者 URI 以结合您的 Orderitems ,并在提交到底层数据模型之前在内容提供者中自己实现解析。

    【讨论】:

    • 你能举个例子吗?
    • 对不起,我也不明白你的想法
    • 我认为这个想法是为这种情况使用一个特殊的 URI,例如 content://authority/orderwithdetails/orderId 。问题是:这在这种情况下不起作用,因为要插入许多细节而不仅仅是一个。
    猜你喜欢
    • 2018-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-16
    • 1970-01-01
    • 2023-01-09
    • 1970-01-01
    相关资源
    最近更新 更多