25

次の質問があります。3 つのエンティティがあり、OneToOne 単方向を使用しています。

エンティティ1

@Entity
public class Entity1 implements Serializable{

   @Id
   @GeneratedValue(strategy= GenerationType.AUTO)
   Long id;
   String name;
   String value;
}

エンティティ 2

@Entity
public class Entity2 implements Serializable {
  @Id
  @GeneratedValue(strategy=GenerationType.AUTO)
  private Long id;

  @OneToOne(cascade={CascadeType.MERGE, CascadeType.PERSIST})
  Entity1 entity1;
  public Entity1 getEntity1() {
      return entity1;
  }

  String name;
  String value;
}

エンティティ3

@Entity
public class Entity3 implements Serializable {
  @Id
  @GeneratedValue(strategy=GenerationType.AUTO)
  Long id;

  @OneToOne(cascade={CascadeType.MERGE, CascadeType.PERSIST})
  private Entity1 entity1;

  public Entity1 getEntity1() {
      return entity1;
  }

  public void setEntity1(Entity1 entity1) {
      this.entity1 = entity1;
  }

  String name;
  String value;
}

小さなテスト:

public void testApp()
   {
    EntityManager em = TestHibernateUtil.getEntityManager();
    em.getTransaction().begin();
    Entity1 entity1 = new Entity1();
    entity1.name = "Name1";
    entity1.value = "Value1";

    Entity2 entity2 = new Entity2();
    entity2.name = "Name2";
    entity2.value = "Value2";
    entity2.setEntity1(entity1);
    **em.merge(entity2);**// if change that to persist - I get one Entity1

    Entity3 entity3 = new Entity3();
    entity3.name = "Name3";
    entity3.value = "Value3";
    entity3.setEntity1(entity1);
    **em.merge(entity3);** // if change that to persist - I get one Entity1
    em.getTransaction().commit();
 }

したがって、上記のテストを調べるとem.merge、トランザクションのコミット後に永続コンテキストで Entity1 の 2em.persistつのエンティティを取得する場合は、永続コンテキストで Entity1 のエンティティを 1 つ取得します。誰かがなぜそれが起こるのか説明したり、いくつかのドキュメントを指摘したりできますか?

4

2 に答える 2

20

DannyMo の素晴らしい回答に異議を唱えることは夢にも思いませんが、追加したいと思いました。

Persist と Merge は、特定のオブジェクトのマネージド インスタンスを 1 つ保持する方法として設計されています。

永続化を使用すると、オブジェクトがまだ存在しないことを意味するため、オブジェクトを一意のマネージド インスタンスにしても害はありません。

マージを使用する場合は、オブジェクトのマネージド インスタンスが既に存在している可能性があることを考慮してください。その一意のマネージド インスタンスを置き換えたくありません。他のオブジェクトがマネージド オブジェクトであると信じて参照する可能性があるためです。

マージ後にオブジェクトに対して操作を行いたい場合、正しいマージは次のようになります。

managedObject = em.merge(object); // or just object = em.merge(object) //You cannot do it with persist since it returns null

managedObjectおよびobjectが同じオブジェクト インスタンス チェックを指しているかどうかをチェックしようとするif(managedObject == object)と、false になります (既に管理されているオブジェクトでマージを使用し、操作が無視される場合は true になる可能性があります)。

以前のマージに引数として渡したオブジェクトの古いバージョンでマージを使用する場合、jpa はまだ ID がないため、正しいオブジェクトを見つける方法を知りません。これは新しいオブジェクトであると想定され、新しいマネージド インスタンスが作成されます。

私はかなりの新人です。どこか間違っている場合は修正してください。

于 2013-08-22T20:06:52.817 に答える