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.InvoiceInvoiceBasePersistentオブジェクトをそれぞれ取得する

                         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.InvoiceBaseaddすることで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();

       }

    }