2014-12-02 47 views
2

我需要插入与Order及其相应的Detail相关的数据。Android - 如何将与两个表相关的数据传递给内容提供者的插入方法

如果没有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操作,知道insert操作只接受两个参数:

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

    } 

,当你有一个交易插入关系数据,你在ContentProvider的做些什么N +

在此先感谢。

回答

3

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

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

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

+1

对不起,我没有把这个标记为答案,但因为我不得不回到IOS项目,然后其他的东西出现了,直到昨天我才能回到我的android项目并确认你的解决方案是正确的答案。 – eddy 2015-04-10 12:24:53

+1

没问题。感谢您记住这一点,并在经过这么长时间后提升我!这应该是值得的SO奖励自己。 – 2015-04-10 13:59:56

+1

当你把我放在正确的轨道上,你真的值得。再次非常感谢你,对不起,如果花了我很多时间来标记这个答案,但因为我在空闲时间学习Android,所以我不得不推迟这个个人项目一段时间。最后如果有人觉得有用,这里是一个例子,说明如何在Content Provider中实现'applyBatch'方法https://github.com/google/iosched/blob/master/android/src/main/java/com /google/samples/apps/iosched/provider/ScheduleProvider.java – eddy 2015-04-10 16:09:43

0

你可以设计内容提供者来镜像你的SQLite表,并且使用与上面相同的代码insertOrder

只需使用内容提供商的insert为每个表(URI),进行类似的操作在您的insertOrder方法

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

+0

你认为你可以给我一个例子吗? – eddy 2014-12-03 02:47:16

+1

对不起,我不认为我想你想法 – Axel 2014-12-03 11:04:30

+2

我认为这个想法是使用一个特殊的URI,例如'content:// authority/orderwithdetails/orderId'。问题是:在这种情况下,这不会起作用,因为有很多细节可以插入,而不仅仅是一个。 – 2014-12-08 19:58:15

1

您可以将所有数据放入ContentValues并拥有提供者。您必须获得有关订单详情的一点创意。

在psuedo代码下面,我创建一个关键的“详细信息”,用一个整数然后是项目。

  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; 
    } 
+1

那么没有交易需要? – Axel 2014-12-03 12:05:33

+0

好吧,你可以再调整一下,并在那里进行交易。我只是展示了如何使用ContentValues来传递信息。如果我是你,我会在你的问题中使用代码或修改订单,以便将它写入ContentValues。 – danny117 2014-12-03 21:16:07

+0

谢谢@ danny117。那么ContentProviders基本上只与当时的一个表一起工作? – eddy 2014-12-05 12:22:25

相关问题