/**
* 更新処理
* @param product
*/
public void update(Product product)
throws EntityNotFoundException
{
// ★ Low-level Datastore
API
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
Transaction tx = null;
EntityConverter entityConverter = new EntityConverter();
FieldMapper fieldMapper = new FieldMapper();
int NUM_RETRIES = 3;
try {
KeyUtils keyUtils = new KeyUtils(BASE_KIND_CLASS);
for (int r = 0; r < NUM_RETRIES; r++)
{
try {
tx = datastore.beginTransaction();
logger.info("tx begin.");
if (product != null) {
Key parentKey = keyUtils.getBaseKeyBuilder().getKey();
Key currentKey = keyUtils.getChildKey(RECORD_KIND_CLASS, product.getOriginalKey());
Entity entity = datastore.get(tx, currentKey);
Product current = (Product)new EntityConverter().convert(RECORD_KIND_CLASS, entity);
// 業務アプリによる楽観的ロック
if (!current.getRevision().equals(product.getRevision())) {
throw new ConcurrentModificationException();
// 削除済データ
} else if (!"".equals(current.getDeleted())) {
throw new EntityNotFoundException(currentKey);
} else {
// Revisionを1上げ、登録
Product target = new Product();
// 更新があるものだけをセット
fieldMapper.setValue(current, target); // Persistent項目のみ
fieldMapper.setValue(product, target); // Persistent項目のみ
target.setId(current.getId());
// 更新カウントアップ
target.setRevision(target.getRevision() + 1);
// キーの設定
target.updateKeyItem();
String currentTime
= getCurrentTime();
target.setUpdated(currentTime);
datastore.put(tx, entityConverter.generate(
target, keyUtils.getKeyName(target.getOriginalKey()), parentKey));
// 以前のものは削除し、履歴として残す
current.setDeleted(currentTime);
datastore.put(tx, entityConverter.generate(
current, keyUtils.getKeyName(current.getOriginalKey()), parentKey));
}
}
logger.info("commit.");
tx.commit();
break;
} catch (DatastoreTimeoutException e) {
logger.info("DatastoreTimeoutException:"+e.getMessage());
if (r == (NUM_RETRIES - 1)) {
throw e;
}
logger.info("rollbacked.");
try {
tx.rollback();
} catch (Throwable ee) {}
} catch (IllegalStateException e)
{
// トランザクションのコミットやロール バックがすでに行われている場合、
// またはコミットやロール バックの試行に失敗している場合。
logger.info("IllegalStateException:"+e.getMessage());
throw e;
} catch (DatastoreFailureException e) {
// データベース エラーが発生する場合に発生。再試行しない。
logger.info("DatastoreFailureException:"+e.getMessage());
throw e;
} catch (ConcurrentModificationException
e) {
logger.info("ConcurrentModificationException:"+e.getMessage());
throw e;
}
} // for loop
} finally {
if (tx.isActive())
{
logger.info("rollbacked.");
try {
tx.rollback();
} catch (Throwable e) {}
}
}