9

以前にパーサイトされたエンティティがあり、@OneToMany別のエンティティと関係があります。新しいエンティティを追加するには、新しいエンティティを管理対象オブジェクトに追加しcascadeType.ALL、変更を永続化するために使用します。新しく作成されたオブジェクトの ID を取得したり、マージで使用した元の (管理されていない) オブジェクトを取得して ID を更新したりする方法はありますか?

疑似コードでは、次のことが起こると予想されます。

  1. マージされたエンティティの新しいコピーが返されます
  2. 古いコピーは新しいエンティティ用に更新されます

例: 親 A、id=13 子 B、id=0

merge本質的に、私は親でa を発行したいのですが、子でカスケードpersistします (元の子インスタンスがコピーされずに更新されるように)。

明らかに、これは起こりません。プロバイダーとして休止状態を使用しています。

4

4 に答える 4

9

Stackoverflowの投稿JPA のドキュメントには、調査を行えば答えがあります。

私が望むことを行う方法はpersist管理対象の親で使用することです。これは親の変更を無視しますが、カスケードpersistします (カスケードするように設定されている場合)。その後、子オブジェクトは正しい ID を持つようになります。

....
JPAEntity newObject=new JPAEntity();
managedObject.addChild(newObject);
em.persist(managedObject)
newObject.getId() //work fine!
于 2013-07-24T10:01:24.700 に答える
1

持続性プロバイダーの eclipselink にも同様の問題がありました。一時的な「クライアント orderID」を持つクライアント データベースからサーバー データベース内の既存の顧客に新しい注文を追加する必要がありました。今後のクライアント要求には「サーバーの orderID」が必要だったので、マップ (clientID、serverID) を作成してクライアントに送り返したいと思いました。基本的に私のアプローチは、新しく追加された子注文のコピーへの参照を取得することです。親クラス customer のリストの最後に常に追加され、その事実を使用して取得されます。

Customer と Order というエンティティ クラスを使用します。ここで、Customer には注文のリスト (LinkedList) があります。

親顧客クラス: ...

    @OneToMany(mappedBy = "customer", cascade=CascadeType.ALL, orphanRemoval = true)
    private List<Order> orders = new LinkedList<Order>();

    public Order getLastOrder() {
      return orders.get(orders.size()-1);
    }

子注文クラス:

    @ManyToOne(optional=false)
    private Customer customer;

サーブレット:

    Customer customer = customerService.findByID(customerID); //existing customer
    Order order = new Order();
    //add attributes to new order
    customer.addOrder(order);
    customerService.update(customer); //generates keys for children
    order = customer.getLastOrder();
    Long orderID = order.getID; //Nullpointer exception

CustomerService は EntityManager.merge で顧客を更新しますが、サーブレットの参照を更新するのを忘れていました:

CustomerService クラス:

    public void update(Customer entity) {
      entityManager.merge(entity);
    }  

私はこのように解決しました: CustomerService クラス:

    public Customer update(Customer entity) {
      return entityManager.merge(entity);
    }

サーブレット: ....

    customer = customerService.update(customer); //generates keys for children

今、すべてが正常に動作します。

于 2014-02-05T13:49:20.870 に答える
1

変更を永続化する前に、関係の両方のサイトを設定していることを確認してください。

child.setParent(parent);
parent.getChildren().add(child);
Parent parentWithId = em.merge(parent);
em.flush(); // make sure that the persistence context and database are in sync
parent.getId(); // works
parent.getChildren().get(0).getId(); // should also work
于 2013-07-23T17:13:34.177 に答える
1

新しいエンティティの生成された ID を「見る」ことができるはずです。

  • トランザクションのコミット後、または

  • トランザクションがアクティブな間em.flush()(どこemにあなたの)の後。EntityManager

エンティティ間のすべての関係は、永続化の前に Java データ構造で解決する必要があることにも注意してください。親への子の参照は「設定」する必要があり、その逆も同様です。

于 2013-07-23T16:53:46.603 に答える