Google Data 通訊協定中的批次處理

批次處理可讓您在單一要求中執行多項作業,而不需個別提交每項作業。

注意:您必須使用最新版本的 Google Data API 用戶端程式庫才能執行批次作業。JavaScript 用戶端程式庫不支援批次作業。

目標對象

本文適用於想透過批次處理單一要求提交多項作業的程式設計師。

這份文件假設您已熟悉 GData Java 用戶端程式庫的使用方式。本文件中的範例說明如何使用 Java 用戶端程式庫執行批次作業。

本文中的範例僅適用於 Google Base Data API。但其他服務也可能提供批次功能。

注意事項:其他用戶端程式庫的通訊協定和一般程序相同,但執行批次要求的特定方法可能不同。詳情請參閱用戶端程式庫專屬說明文件。

簡介

您可以使用 GData 批次動態饋給來收集多個插入、更新、刪除和查詢作業,然後一次提交及執行這些作業。

舉例來說,以下資訊提供包含四個作業:

<feed>
  <entry>
    <batch:operation type="insert"/>
    ... what to insert ...
  </entry> 
  <entry>
    <batch:operation type="update"/>
    ... what to update ...
  </entry>
  <entry>
    <batch:operation type="delete"/>
    ... what to delete ...
  </entry>
  <entry>
    <batch:operation type="query"/>
    ... what to query ...
  </entry>
</feed>

服務會盡可能執行要求的所有變更,並傳回用來評估每項作業成功或失敗狀態的狀態資訊。

服務會嘗試在批次中執行每項作業,即使批次中包含的部分作業失敗。

提交批次要求

批次要求應以 HTTP POST 的形式傳送至批次網址。不同的動態饋給支援不同的批次作業。唯讀動態饋給僅支援查詢。

如要查詢特定動態饋給是否支援批次作業,您可以查詢該動態饋給。如果動態饋給包含動態饋給層級的「批次」連結關係,表示動態饋給支援批次作業。

「批次」連結關係是包含 rel="http://schemas.google.com/g/2005#batch"<link> 元素。連結關係的 href 屬性定義用於張貼批次作業動態饋給文件的網址。

舉例來說,如果您執行:GET http://www.google.com/base/feeds/items (一般 Google Base 的「items」動態饋給),您可能會收到以下回應:

<feed xmlns=...
  <id>http://www.google.com/base/feeds/items</id>
  <link rel="http://schemas.google.com/g/2005#feed"
    type="application/atom+xml"
    href="http://www.google.com/base/feeds/items"/>
  <link rel="http://schemas.google.com/g/2005#post"
    type="application/atom+xml"
    href="http://www.google.com/base/feeds/items"/>
  <link rel="http://schemas.google.com/g/2005#batch"
    type="application/atom+xml"
    href="http://www.google.com/base/feeds/items/batch"/>
  ...
</feed> 

在這個範例中,批次網址為 http://www.google.com/base/feeds/items/batch

編寫批次作業動態饋給

作業動態饋給含有要插入、更新、刪除或查詢的項目清單。每項作業都會由 <batch:operation type="insert|update|delete|query"/> 元素定義。

這個元素可以是 <feed> 元素的直接子項、動態饋給中任何項目的直接子項,或兩者皆是。包含在項目中,會指定要對特定項目執行的作業。加入動態饋給時,這個元素會指定在沒有 <batch:operation/> 元素的任何項目中執行的預設作業。

當項目和動態饋給都未指定作業時,預設作業會是 insert

應用程式不可在單一批次動態饋給中,為同一項項目套用多項作業。如果您為同一個項目指定多個作業,系統會無法判定結果。

為提高效能,系統可能不會按照要求的順序處理作業。不過,最終結果一律與處理順序相同。

在 XML 中,您傳送至伺服器的位元組數量不得超過 1 MB (1,048,576 位元組)。一般來說,您可以要求的作業數沒有限制,只要總位元組大小不超過 1 MB 即可。不過,部分服務可能會設有額外限制。

如要使用批次作業,您必須在 <feed> 元素中加入批次命名空間宣告做為屬性:

<feed 
  xmlns="http://www.w3.org/2005/Atom"
  xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/"
  ...
  xmlns:batch="http://schemas.google.com/gdata/batch">

插入作業

插入作業如下所示:

<batch:operation type="insert">

插入作業相當於發布 POST 的項目。作業成功後,系統會傳回整個項目內容,包含更新的文件 <id> 元素和 <batch:status code="201"/> 元素。

以下是插入要求成功的範例:

<entry>
  <title type="text">...</title>
  <content type="html">...</content>
  <batch:id>itemA</batch:id>
  <batch:operation type="insert"/>
  <g:item_type>recipes</g:item_type>
  ... 
</entry>

以下是插入成功要求的回應範例:

<entry>
  <batch:status code="201"/>
  <batch:id>itemA</batch:id>
  <batch:operation type="insert"/>
  <id>http://www.google.com/base/feeds/items/17437536661927313949</id>
  <link rel="self" type="application/atom+xml"
    href="http://www.google.com/base/feeds/items/17437536661927313949"/>
  <title type="text">...</title>
  <content type="html">...</content>
  <g:item_type>recipes</g:item_type>
  ... 
</entry>

更新作業

<batch:operation type="update">

更新作業相當於在該項目的 <id> 元素參照的網址上執行 PUT。作業成功後,系統會使用 <batch:status code="200"/> 元素傳回整個項目內容。

注意事項:使用某些動態饋給時,您還需要透過批次更新要求來指定該項目的 rel="edit" 連結。這些動態饋給包含支援 Google Data 通訊協定 v1 樣式的樂觀並行,以及不含網址 ID 的動態饋給。

以下是更新要求的範例:

<entry>
  <id>http://www.google.com/base/feeds/items/17437536661927313949</id>
  <batch:operation type="update"/>
  ...
</entry>

以下是成功回應的範例:

<entry>
  <batch:status code="200"/>
  <id>http://www.google.com/base/feeds/items/17437536661927313949</id>
  <batch:operation type="update"/>
  ... 
</entry>

注意:某些資訊提供使用強大的 ETag,可防止您不小心修改其他人的變更。針對這些資訊提供中某個項目的批次更新要求時,您必須在該項目的 gd:etag 屬性中提供 ETag 值。例如,<entry gd:etag="'F08NQAxFdip7IWA6WhVR'">...<batch:operation type="update"/>...

部分更新作業

對於支援部分更新的動態饋給,您還可以在批次要求中使用。部分更新作業相當於在該項目 <id> 元素參照的網址上執行 PATCH。作業成功後,系統會使用 <batch:status code="200"/> 元素傳回整個項目內容。

注意事項:使用某些動態饋給時,您還需要透過批次更新要求來指定該項目的 rel="edit" 連結。這些動態饋給包含支援 Google Data 通訊協定 v1 樣式的樂觀並行,以及不含網址 ID 的動態饋給。

<batch:operation type="patch"/>

以下是部分更新要求的範例:

<entry gd:fields="content" gd:etag="FE8LQQJJeSp7IWA6WhVa">
  <id>http://www.google.com/calendar/feeds/jo@gmail.com/private/full/entryID</id>
  <batch:operation type="patch"/>
  <title>New title</title>
</entry>

以下是成功回應的範例:

<entry gd:etag="FE8LQQJJeSp7IWA6WhVa">
  <batch:status code="200"/>
  <id>http://www.google.com/calendar/feeds/jo@gmail.com/private/full/entryID</id>
  <batch:operation type="patch"/>
  <title>New title</title>
  <content></content>
  ...rest of the entry...
</entry>

可刪除作業

<batch:operation type="delete">

刪除作業相當於在該項目 <id> 元素參照的網址上執行 DELETE。如果是刪除作業,只需傳送 <id> 元素即可刪除項目。系統會忽略您在 batch: 命名空間以外元素的任何其他資訊。作業成功時,系統會傳回含有相同 ID 的 <batch:status code="200"/> 元素。

注意:使用某些資訊提供時,您還需要透過批次刪除要求來指定該項目的 rel="edit" 連結。這些動態饋給包含支援 Google Data 通訊協定 v1 樣式的樂觀並行,以及不含網址 ID 的動態饋給。

以下是刪除要求的範例:

<entry>
  <batch:operation type="delete"/>
  <id>http://www.google.com/base/feeds/items/17437536661927313949</id>
</entry>

以下是成功回應的範例:

<entry>
  <batch:operation type="delete"/>
  <id>http://www.google.com/base/feeds/items/17437536661927313949</id>
  <batch:status code="200" reason="Success"/>
</entry>

注意:某些資訊提供使用強大的 ETag,可防止您不小心修改其他人的變更。為這些資訊提供項目中的某個項目提出大量刪除要求時,您必須在該項目的 gd:etag 屬性中提供 ETag 值。例如,<entry gd:etag="'F08NQAxFdip7IWA6WhVR'">...<batch:operation type="delete"/>...

查詢作業

<batch:operation type="query">

查詢作業相當於在該項目 <id> 元素參照的網址上執行 GET。作業成功後,系統會傳回整個項目內容。

注意事項:使用某些資訊提供時,您也需要以批次查詢要求指定該項目的 rel="self" 連結。屆時如果動態饋給的 ID 不是網址,就屬於這類動態饋給。

以下是查詢要求的範例:

<entry>
  <id>http://www.google.com/base/feeds/items/1743753666192313949</id>
  <batch:operation type="query"/>
</entry>

以下是成功回應的範例:

<entry>
  <id>http://www.google.com/base/feeds/items/1743753666192313949</id>
  <batch:operation type="query"/>
  <batch:status code="200" reason="Success"/>
   ...
</entry>

追蹤作業

GData 輸入結果不一定會與要求的順序傳回。您可以使用 ID,在其生命週期中追蹤作業。

更新、刪除及查詢作業時,您可以使用項目本身的 ID 來追蹤作業。

如果是插入作業,由於沒有 ID,您可以傳入作業 ID。這個 ID 可用來將結果項目連結至要求項目。作業 ID 會透過 <batch:id> 元素傳遞。

GData 會針對每項作業傳回回應,指出作業成功或失敗。每個回應都會找出相關項目。針對更新、刪除或查詢作業或成功插入作業,系統一律會傳回項目 ID。如果您已指定批次 ID,系統會一併傳回這個 ID。由於插入作業失敗時沒有相關聯的項目 ID,因此只會傳回批次 ID。

使用每項作業的 ID 時,您只能重試失敗的作業,而不必重新提交整批作業。

<batch:id> 的內容是用戶端定義的字串值,會在對應的回應項目中回呼。您可以指定任何值,協助用戶端將回應與原始要求中的項目建立關聯。即使作業失敗,此元素也會依照對應項目原樣進行回音。GData 絕不會儲存或解讀這個批次 ID 的內容。

以下為批次作業資訊提供的範例。請注意,<batch:id> 元素會將這項作業標示為 itemB

<entry>
  <title type="text">...</title>
  <content type="html">...</content>
  <batch:id>itemB</batch:id>
  <batch:operation type="insert"/>
  <g:item_type>recipes</g:item_type>
</entry>

以下範例顯示回應此作業所傳回的批次狀態項目。

<entry>
  <id>http://www.google.com/base/feeds/items/2173859253842813008</id>
  <published>2006-07-11T14:51:43.560Z</published>
  <updated>2006-07-11T14:51: 43.560Z</updated>
  <title type="text">...</title>
  <content type="html">...</content>
  <link rel="self" 
    type="application/atom+xml" 
    href="http://www.google.com/base/feeds/items/2173859253842813008"/>
  <link rel="edit" 
    type="application/atom+xml" 
    href="http://www.google.com/base/feeds/items/2173859253842813008"/>
  <g:item_type>recipes</g:item_type>
  <batch:operation type="insert"/>
  <batch:id>itemB</batch:id>
  <batch:status code="201" reason="Created"/>
</entry>

處理狀態碼

狀態碼由下列元素表示:

<batch:status code="200|201|404|500|..." reason="reason" [content-type="type"]/>

回應資訊提供中的每個項目都包含一個 <batch:status> 元素。這個元素會描述執行這項作業時發生的情況。這個程式碼會模擬如果傳送的是個別作業,而非批次批次傳送時傳送的 HTTP 回應。

您必須查看回應中每個項目的 <batch:status> 元素,看看相關聯的作業是否已成功處理完畢。code="n" 屬性包含 GData 狀態碼

狀態說明

<batch:status> 元素的 reason="reason" 屬性包含更詳細的作業狀態說明。

內容類型

<batch:status> 元素中的 content-type="type" 屬性包含 <batch:status> 元素所含資料的 MIME 類型。這會對應至 HTTP 狀態回應的 Content-Type 標頭。此屬性為選用項目。

設定內容類型後,<batch:status> 元素的主體會說明處理該項目時發生錯誤。

識別服務中斷的作業

服務中斷時,回應中會包含以下元素:

<batch:interrupted reason="reason" success="N" failures="N" parsed="N">

這個元素表示批次處理作業中斷,所有嘗試中斷中斷的原因均失敗。部分項目可能已順利處理完畢。所有未於這個時間點前回報為成功的項目均遭到捨棄。

這個元素極為罕見,通常代表要求內文中傳送的動態饋給格式不正確。

<batch:status> 元素一樣,您可以在 reason 屬性中找到短狀態碼。系統也可能會在元素內顯示較長的回應。

批次作業和狀態資訊提供範例

以下為可傳送到伺服器的批次作業資訊提供。這項資訊提供會要求伺服器刪除兩個項目,並新增兩個項目。請注意, <feed> 元素必須包含批次命名空間處理,如下方範例所示。

POST : http://www.google.com/base/feeds/items/batch
<?xml version="1.0" encoding="UTF-8"?>
<feed
  xmlns="http://www.w3.org/2005/Atom"
  xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/"
  xmlns:g="http://base.google.com/ns/1.0"
  xmlns:batch="http://schemas.google.com/gdata/batch">
  <title type="text">My Batch Feed</title>
  <entry>
    <id>http://www.google.com/base/feeds/items/13308004346459454600</id>
    <batch:operation type="delete"/>
  </entry>
  <entry>
    <id>http://www.google.com/base/feeds/items/17437536661927313949</id>
    <batch:operation type="delete"/>
  </entry>
  <entry>
    <title type="text">...</title>
    <content type="html">...</content>
    <batch:id>itemA</batch:id>
    <batch:operation type="insert"/>
    <g:item_type>recipes</g:item_type>
  </entry>
  <entry>
    <title type="text">...</title>
    <content type="html">...</content>
    <batch:id>itemB</batch:id>
    <batch:operation type="insert"/>
    <g:item_type>recipes</g:item_type>
  </entry>
</feed>

假設這兩個插入項目都正常運作,但兩個刪除作業中的其中一個失敗。在這種情況下,批次狀態資訊提供可能如下所示。請注意,相較於批次作業動態饋給,這些項目已重新排序。

<?xml version="1.0" encoding="UTF-8"?>
<feed
  xmlns="http://www.w3.org/2005/Atom"
  xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/"
  xmlns:g="http://base.google.com/ns/1.0"
  xmlns:batch="http://schemas.google.com/gdata/batch">
  <id>http://www.google.com/base/feeds/items</id>
  <updated>2006-07-11T14:51:42.894Z</updated>
  <title type="text">My Batch</title>
  <link rel="http://schemas.google.com/g/2005#feed"
    type="application/atom+xml"
    href="http://www.google.com/base/feeds/items"/>
  <link rel="http://schemas.google.com/g/2005#post"
    type="application/atom+xml"
    href="http://www.google.com/base/feeds/items"/>
  <link rel=" http://schemas.google.com/g/2005#batch"
    type="application/atom+xml"
    href="http://www.google.com/base/feeds/items/batch"/>
  <entry>
    <id>http://www.google.com/base/feeds/items/2173859253842813008</id>
    <published>2006-07-11T14:51:43.560Z</published>
    <updated>2006-07-11T14:51: 43.560Z</updated>
    <title type="text">...</title>
    <content type="html">...</content>
    <link rel="self"
      type="application/atom+xml"
      href="http://www.google.com/base/feeds/items/2173859253842813008"/>
    <link rel="edit"
      type="application/atom+xml"
      href="http://www.google.com/base/feeds/items/2173859253842813008"/>
    <g:item_type>recipes</g:item_type>
    <batch:operation type="insert"/>
    <batch:id>itemB</batch:id>
    <batch:status code="201" reason="Created"/>
  </entry>
  <entry>
    <id>http://www.google.com/base/feeds/items/11974645606383737963</id>
    <published>2006-07-11T14:51:43.247Z</published>
    <updated>2006-07-11T14:51: 43.247Z</updated>
    <title type="text">...</title>
    <content type="html">...</content>
    <link rel="self"
      type="application/atom+xml"
      href="http://www.google.com/base/feeds/items/11974645606383737963"/>
    <link rel="edit"
      type="application/atom+xml"
      href="http://www.google.com/base/feeds/items/11974645606383737963"/>
    <g:item_type>recipes</g:item_type>
    <batch:operation type="insert"/>
    <batch:id>itemA</batch:id>
    <batch:status code="201" reason="Created"/>
  </entry>
  <entry>
    <id>http://www.google.com/base/feeds/items/13308004346459454600</id>
    <updated>2006-07-11T14:51:42.894Z</updated>
    <title type="text">Error</title>
    <content type="text">Bad request</content>
    <batch:status code="404"
      reason="Bad request"
      content-type="application/xml">
      <errors>
        <error type="request" reason="Cannot find item"/>
      </errors>
    </batch:status>
  </entry>
  <entry>
    <id>http://www.google.com/base/feeds/items/17437536661927313949</id>
    <updated>2006-07-11T14:51:43.246Z</updated>
    <content type="text">Deleted</content>
    <batch:operation type="delete"/>
    <batch:status code="200" reason="Success"/>
  </entry>
</feed>

使用 GData Java 用戶端程式庫的批次功能

本節說明如何使用 GData Java 用戶端程式庫的批次功能,提交一組插入、更新和/或刪除要求。

本節提供的範例使用 Google Base API。

除了標準 GData 和 Google Base 類別之外,請先匯入需要的類別:

import com.google.gdata.data.batch.*;
import com.google.api.gbase.client.*;

如要提交批次要求,您必須從動態饋給取得批次網址。下列程式碼片段示範如何執行這項作業,假設 feed 是包含動態饋給相關資訊的 GoogleBaseFeed 物件:

Link batchLink = feed.getLink(Link.Rel.FEED_BATCH, Link.Type.ATOM);
if (batchLink != null) {
  URL batchUrl = new URL(batchLink.getHref());
  ... // batch handling
} else {
  // batching is not supported for this feed
}

下列程式碼片段準備了一個動態饋給,並會在單一作業中插入兩個項目:

GoogleBaseEntry entry1 = new GoogleBaseEntry();
...   // initialize entry 1 content
BatchUtils.setBatchId(entry1, "A"); // A is the local batch ID for this entry
feed.addEntry(entry1);
GoogleBaseEntry entry2 = new GoogleBaseEntry();
... // initialize entry 2 content
BatchUtils.setBatchId(entry2, "B"); // B is the local batch ID for this entry
feed.addEntry(entry2);

這個範例中的程式碼絕不會明確指出要為這些項目執行的動作為 insert。您不需要指定,因為插入功能是預設的作業。

如要傳送批次動態饋給並接收結果,請呼叫 Service.batch 方法。

Service.insert 一樣,Service.batch 會傳回插入新 <atom:id> 值的插入項目。傳回的項目會包含在 GoogleBaseFeed 物件中。

如果您想在插入其他兩個項目時同時刪除第三個項目 (您已擷取並儲存在 entry3 中),可以使用以下程式碼:

GoogleBaseEntry toDelete = new GoogleBaseEntry();


toDelete.setId(entry3.getId());
BatchUtils.setBatchOperationType(toDelete, BatchOperationType.DELETE);

feed.addEntry(toDelete);


GoogleBaseFeed result = service.batch(batchUrl, feed);

此處的 servicecom.google.gdata.client.Service 的執行個體。

如要更新項目,請指定 OperationType.UPDATE,並以需要的變更進行初始化,而不是保留空白。

這些範例使用 Google Base 資料 API。如果您將 service.batch 與其他類型的 GData 服務搭配使用,請將適當的類別、項目和服務類別替換為 GoogleBaseFeedGoogleBaseEntryGoogleBaseService 類別。

批次作業的結果不一定會按照要求的順序傳回。在上述範例中,結果動態饋給很可能包含 entry2,後面接著 entry1。請勿假設以任何特定順序傳回項目。

批次作業動態饋給應為每個插入作業指派專屬的批次 ID,如追蹤作業中所述。在上述範例中,批次 ID 為 AB。因此,如要瞭解要求作業的狀態,請重複傳回傳回批次動態饋給中的項目,並比較其批次 ID 或項目 ID,如下所示:

for (GoogleBaseEntry entry : result.getEntries()) {
  String batchId = BatchUtils.getBatchId(entry);      
  if (BatchUtils.isSuccess(entry)) {     
    if ("A".equals(batchId)) {       
      entry1 = entry;     } 
    else if ("B".equals(batchId)) {       
      entry2 = entry;     } 
    else if (BatchUtils.getBatchOperationType(entry) 
      == BatchOperationType.DELETE) {       
      System.out.println("Entry " + entry.getId() +
      " has been deleted successfully.");     
    }      
  } else {     
    BatchStatus status = BatchUtils.getBatchStatus(entry);     
    System.err.println(batchId + " failed (" +                
      status.getReason() + ") " +  status.getContent());      
    }    
  } 

傳回的動態饋給中的每個項目都有相關聯的 BatchStatus 物件。 BatchStatus 物件包含 HTTP 傳回代碼和回應,說明項目處理期間發生錯誤的原因。您必須檢查每個項目的 HTTP 傳回碼,以得知作業是否成功。

使用上述方法的便利方法 BatchUtils.isSuccess 完成檢查。在本範例中,這相當於:BatchUtils.getBatchStatus(entry) < 300

如要進一步瞭解狀態碼和回應,請參閱處理狀態碼一文。

返回頁首