@Hibernateで不変
1. 概要
この記事では、Hibernateでエンティティ、コレクション、または属性Immutableを作成する方法について説明します。
デフォルトでは、フィールドは変更可能です。つまり、フィールドの状態を変更する操作を実行できます。
2. Maven
プロジェクトを起動して実行するには、最初に必要な依存関係をpom.xmlに追加する必要があります。 そして、Hibernateを使用しているときに、対応する依存関係を追加します。
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.6.7.Final</version>
</dependency>
また、 HSQLDB を使用しているため、次のものも必要です。
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>2.3.4</version>
</dependency>
3. エンティティへの注釈
まず、単純なエンティティクラスを定義しましょう。
@Entity
@Immutable
@Table(name = "events_generated")
public class EventGeneratedId {
@Id
@Column(name = "event_generated_id")
@GeneratedValue(generator = "increment")
@GenericGenerator(name = "increment", strategy = "increment")
private Long id;
@Column(name = "name")
private String name;
@Column(name = "description")
private String description;
// standard setters and getters
}
お気づきのとおり、エンティティにはすでに @Immutable アノテーションが追加されているため、Eventを保存しようとすると次のようになります。
@Test
public void addEvent() {
Event event = new Event();
event.setId(2L);
event.setTitle("Public Event");
session.save(event);
session.getTransaction().commit();
session.close();
}
次に、出力を取得する必要があります。
Hibernate: insert into events (title, event_id) values (?, ?)
アノテーションを削除しても出力は同じである必要があります。つまり、アノテーションに関係なくエンティティを追加しようとしても効果はありません。
EventGeneratedIdエンティティにGeneratedValueアノテーションを追加したことにも注意してください。ただし、これはエンティティを作成するときにのみ違いがあります。 これは、IDの生成戦略を指定しているためです。他の操作は、 Immutable アノテーションにより、Idフィールドに影響を与えません。
3.1. エンティティの更新
これで、エンティティの保存に問題はありませんでした。更新してみましょう。
@Test
public void updateEvent() {
Event event = (Event) session.createQuery(
"FROM Event WHERE title='My Event'").list().get(0);
event.setTitle("Public Event");
session.saveOrUpdate(event);
session.getTransaction().commit();
}
Hibernateは、例外をスローせずにupdate操作を単に無視します。 ただし、 @Immutable アノテーションを削除すると、異なる結果が得られます。
Hibernate: select ... from events where title='My Event'
Hibernate: update events set title=? where event_id=?
これは、オブジェクトが可変になり(可変は、注釈が含まれていない場合のデフォルト値です)、更新がその役割を果たせるようになることを示しています。
3.2. エンティティの削除
エンティティの削除に関しては、次のようになります。
@Test
public void deleteEvent() {
Event event = (Event) session.createQuery(
"FROM Event WHERE title='My Event'").list().get(0);
session.delete(event);
session.getTransaction().commit();
}
変更可能かどうかに関係なく、削除を実行できます。
Hibernate: select ... from events where title='My Event'
Hibernate: delete from events where event_id=?
4. コレクションの注釈
これまで、アノテーションがエンティティにどのように作用するかを見てきましたが、冒頭で述べたように、コレクションにも適用できます。
まず、Eventクラスにコレクションを追加しましょう。
@Immutable
public Set<String> getGuestList() {
return guestList;
}
以前と同じように、事前に注釈を追加したので、先に進んでコレクションに要素を追加しようとすると、次のようになります。
org.hibernate.HibernateException:
changed an immutable collection instance: [com.baeldung.entities.Event.guestList#1]
今回は例外が発生します。これは、コレクションではコレクションを追加または削除できないためです。
4.1. コレクションの削除
Collection が不変であるという別のシナリオでは、削除しようとして@Cascadeアノテーションを設定するたびに例外がスローされます。
したがって、 @Immutable が存在し、削除しようとすると、次のようになります。
@Test
public void deleteCascade() {
Event event = (Event) session.createQuery(
"FROM Event WHERE title='Public Event'").list().get(0);
String guest = event.getGuestList().iterator().next();
event.getGuestList().remove(guest);
session.saveOrUpdate(event);
session.getTransaction().commit();
}
出力:
org.hibernate.HibernateException:
changed an immutable collection instance:
[com.baeldung.entities.Event.guestList#1]
5. XMLノート
最後に、 mutable =false属性を介してXMLを使用して構成を行うこともできます。
<hibernate-mapping>
<class name="com.baeldung.entities.Event" mutable="false">
<id name="id" column="event_id">
<generator class="increment"/>
</id>
<property name="title"/>
</class>
</hibernate-mapping>
ただし、基本的にはアノテーションメソッドを使用して例を実装したため、XMLを使用して詳細を説明することはしません。
6. 結論
この簡単な記事では、Hibernateの便利な @Immutable アノテーションと、それがデータのより良いセマンティクスと制約を定義するのにどのように役立つかを探ります。
いつものように、これらすべての例とスニペットの実装は、GitHubプロジェクトにあります。 これはMavenベースのプロジェクトであるため、インポートと実行が簡単である必要があります。