6.1 深い依存関係の管理

@OneToManyアノテーションなどに関するさらに便利で興味深い点もいくつかあります。これらにはすべて、一般的に使用される 4 つのオプションがあります。

  • カスケード= CascadeType.ALL
  • orphanRemoval = true
  • フェッチ= FetchType.LAZY

次に、それらをより詳細に分析します。そして、最も興味深いCascadeTypeから始めます。このパラメータは、メイン エンティティを変更した場合に依存エンティティに何が起こるかを決定します。

JPA 仕様では、このパラメータに次の値があります。

  • 全て
  • 持続する
  • マージ
  • 削除
  • リフレッシュ
  • 切り離す

ただし、Hibernate はこの仕様をさらに 3 つのオプションに拡張します。

  • 複製する
  • 保存_更新
  • ロック

もちろん、データベースとその CONSTRANAIS には強い類似点があります。ただし、違いもあります。Hibernate はデータベースでの実際の作業を可能な限り隠そうとするため、これらの Hibernate カスケードはまさに Entity オブジェクトに関するものです。

6.2 カスケードタイプ

カスケード パラメータは、親 (マスター オブジェクト) を変更した場合に依存オブジェクトに何が起こるかを記述します。ほとんどの場合、このパラメータはオブジェクトの依存関係を説明する注釈と一緒に使用されます。

例:

OneToOne(cascade = CascadeType.ALL)

または次のようにします。

@ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})

別のアノテーションとして記述することもできます。

@Cascade({ org.hibernate.annotations.CascadeType.ALL })

ここで、これらの注釈が何を意味するかについて詳しく説明します。

6.3 すべて、永続化、マージ

CascadeType.ALLこれは、親オブジェクトに対して実行するすべてのアクションを、その依存オブジェクトに対しても繰り返す必要があることを意味します。

CascadeType.PERSISTこれは、親オブジェクトをデータベースに保存する場合、その依存オブジェクトについても同じことを行う必要があることを意味します。例:


@Entity
@Table(name="employee")
class Employee {
   @Column(name="id")
   public Integer id;
 
   @OneToOne(cascade = CascadeType.PERSIST, mappedBy="task")
   private EmployeeTask task;
}

このクラスの操作例:


Employee director = new Employee();
EmployeeTask task = new EmployeeTask();
director.task = task;
 
session.persist(director);
session.flush();

Employee タイプのオブジェクトのみを保存します。その依存オブジェクト EmployeeTask はデータベースに自動的に保存されます。

CascadeType.MERGEこれは、データベース内の親オブジェクトを更新する場合、その依存オブジェクトに対しても同じことを行う必要があることを意味します。

6.4 削除、削除、切り離し

CascadeType.REMOVEこれは、データベース内の親オブジェクトを削除する場合、その依存オブジェクトに対しても同じことを行う必要があることを意味します。

CascadeType.DELETE同じ意味です。これらは同義語です。ただ仕様が違うだけです。

CascadeType.DETACHこれは、セッションから親オブジェクトを削除する場合、その依存オブジェクトに対しても同じことを行う必要があることを意味します。例:


@Entity
@Table(name="employee")
class Employee {
   @Column(name="id")
   public Integer id;
 
   @OneToOne(cascade = CascadeType.DETACH, mappedBy="task")
   private EmployeeTask task;
}

このクラスの操作例:


Employee director = new Employee();
EmployeeTask task = new EmployeeTask();
director.task = task;
director.task = task;
session.flush();
 
assertThat(session.contains(director)).isTrue();
assertThat(session.contains(task)).isTrue();
 
session.detach(director);
 
assertThat(session.contains(director)).isFalse();
assertThat(session.contains(task)).isFalse();

CascadeType.REFRESHそして、 CascadeType.SAVE_UPDATE私たちが期待するのと同じように動作します。親オブジェクトで実行されるアクションをその依存オブジェクトに複製します。

6.5 孤立した要素の削除オプション

また、パラメーターに遭遇することもありますorphan。これはオーファン除去の略です。これは、親エンティティのない子エンティティが存在しないことを保証するために使用されます。

OneToOne(orphan = true)

このパラメータが true に設定されている場合、子エンティティが消滅した場合は削除されます。すべてのリンク。とまったく同じではありませんCascade.REMOVE

複数の親エンティティが 1 つの子を参照する状況が発生する場合があります。この場合、親エンティティの削除と一緒に削除されず、それへのすべての参照が無効化された場合にのみ削除されることが有益です。

クラスがあるとします。


@Entity
@Table(name="user")
class Employee {
   @Column(name="id")
   public Integer id;
 
   @OneToMany(cascade = CascadeType.ALL, orphan = true)
   @JoinColumn(name = "employee_id")
   private Set<EmployeeTask> tasks = new HashSet<EmployeeTask>();
}


Employee director = session.find(Employee.class, 4);
EmployeeTask task = director.tasks.get(0);
director.tasks.remove(task)
session.persist(director);
session.flush();

EmployeeTask オブジェクトへの参照が残っていないため、このオブジェクトは削除されます。同時に、誰も親オブジェクトを削除しませんでした。

6.6 フェッチオプション

フェッチ オプションを使用すると、依存オブジェクトのロード方法を制御できます。通常、次の 2 つの値のいずれかをとります。

  • FetchType.LAZY
  • FetchType.EAGER

これはさまざまな落とし穴がある非常に興味深いテーマなので、別の講義でお話したいと思います。