public void update(Invoice invoice) {
PersistenceManager
pm = PMF.get().getPersistenceManager();
FieldMapper
fieldMapper = new FieldMapper();
Transaction tx
= pm.currentTransaction();
int cntRetry = 3;
try {
for (int r = 0; r < cntRetry; r++) {
try {
tx.begin();
if (invoice != null) {
try {
String
invoiceNo = invoice.getInvoiceNo();
long invoiceId = invoice.getId();
// 1.InvoiceとInvoiceBaseのPersistentオブジェクトをそれぞれ取得する
Key
keyInvoice = keyUtils.getChildKey(Invoice.class,
invoiceNo);
Invoice
invoicePersistent = pm.getObjectById(Invoice.class, keyInvoice);
InvoiceBase invoiceBasePersistent
= pm.getObjectById(InvoiceBase.class, keyUtils.getBaseKeyBuilder().getKey());
// 2.invoicePersistentから、いったんdetachCopy
Invoice
invoiceTarget = pm.detachCopy(invoicePersistent);
// 3.コピーしたものに子要素のorderを追記補完
invoiceTarget.setOrder(getOrdersByInvoiceNo(invoiceTarget.getInvoiceNo()));
// リビジョンのカウントアップで使用する
long revisionTarget = invoiceTarget.getRevision();
// 業務アプリによる楽観的ロック
if (revisionTarget != invoice.getRevision())
{
throw new ConcurrentModificationException("Optimistic lock!");
}
else {
// 4.invoiceからinvoiceSource(1品一葉)を取得する。
// orderIdの最大値を更新するためにinvoiceBasePersistentもパラメータとして渡す。
Invoice
invoiceSource = getInvoiceSource(invoice,
invoiceBasePersistent);
// 5.クライアントからのリクエストデータで更新があったものだけをinvoiceTargetにコピーする
fieldMapper.setValue(invoiceSource,
invoiceTarget);
// 6.Key,Id,Revisionを更新
invoiceTarget.setRevision(++revisionTarget);
// 7.InvoiceBaseにaddすることでInvoice以下子要素のorderなどもpersistentになる
//
(makePersistentは不要)
invoiceBasePersistent.addInvoice(invoiceTarget);
// addInvoiceは以下を実行している
//if (invoiceBasePersistent.getInvoiceList()==null)
{
// invoiceBasePersistent.setInvoiceList(new ArrayList<Invoice>());
//}
//invoiceBasePersistent.getInvoiceList().add(invoiceTarget);
}
}
catch (JDOObjectNotFoundException e) {
// 0件更新
throw e;
}
}
tx.commit();
break;
}
catch (JDOCanRetryException e) {
if (r == (cntRetry - 1)) {
throw e;
}
tx.rollback();
}
catch (JDOException e) {
throw e;
}
catch (ConcurrentModificationException e) {
throw e;
}
} // for loop
} finally {
if (tx.isActive()) {
tx.rollback();
}
pm.close();
}
}