AppEngineでKind(テーブル)を削除する方法
Google App Engineではデータを削除したい時にサーバのデータに対してDelete文を実行したりDrop Tableしたりということができません。Kindをdrop(KindにあるEntity[レコード]を全件削除)するには現時点では削除するコードをサーバにデプロイしてブラウザからリクエストを送ります。そこで使用するソースコードを紹介します。
import java.util.ArrayList; import java.util.List; import com.google.appengine.api.datastore.DatastoreService; import com.google.appengine.api.datastore.DatastoreServiceFactory; import com.google.appengine.api.datastore.DatastoreTimeoutException; import com.google.appengine.api.datastore.Entity; import com.google.appengine.api.datastore.FetchOptions; import com.google.appengine.api.datastore.Key; import com.google.appengine.api.datastore.Query; public static void dropKind(String kindName) { DatastoreService ds = DatastoreServiceFactory.getDatastoreService(); Query query = new Query(kindName); query.setKeysOnly(); List<Entity> list = ds.prepare(query).asList(FetchOptions.Builder.withOffset(0)); // ※DatastoreTimeoutException の可能性がありますが省略しています。 List<Key> keys = new ArrayList<Key>(500); for (Entity entity : list) { keys.add(entity.getKey()); if (keys.size() == 500) { try { ds.delete(keys); // batch delete } catch (DatastoreTimeoutException ignore) { } keys.clear(); } } if (keys.size() > 0){ ds.delete(keys); // batch delete ※DatastoreTimeoutException の可能性がありますが省略しています。 } }
使い方は簡単でdropKindの引数にKind名を指定するだけです。おそらくJDOを使っている人は下記のようなコードになると思います。
例)dropKind(Emp.class.getSimpleName());
- 解説
- KindのKey(PK)を全件取得
- KindのKeyを取得する際に、query.setKeysOnly();をしています。データ(プロパティ値)が不要な場合はsetKeysOnlyすることで取得が4倍近く早くなります。
- KeyをListに詰める
- DatastoreServiceのdeleteは1つのKeyを引数に取ることもできますが、KeyをListに詰めた後にds.delete(keys);する事でbatch deleteとなり高速に削除できます。
- 500件毎にdelete
- 500件毎に削除しているのはDatastoreServiceのput(insert/update)およびdeleteは最大500件だからです。
- ※DatastoreTimeoutExceptionをtry catch。DatastoreTimeoutExceptionが発生したら途中まで消えたり消えなかったりします。
- KindのKey(PK)を全件取得
*一応書いておくと、このメソッド一回で確実にKindをDropすることを保証するものではありません。何回も実行して下さいな。もし、これでも件数が多くてだめな場合はTaskQueueで件数を分割して投げまくって下さい。