Hibernateで@Immutable

1概要

この記事では、エンティティ、コレクション、または属性をhttps://docs.jboss.org/hibernate/orm/5.2/javadocs/org/hibernate/annotations/Immutable.html[Immutable]に作成する方法について説明します。休止状態

デフォルトでは、フィールドは変更可能です。つまり、フィールドはフィールドの状態を変更する操作を実行できます。

2 Maven

私たちのプロジェクトを立ち上げるには、まず pom.xml に必要な依存関係を追加する必要があります。そして、Hibernateを使っているので、対応するhttps://search.maven.org/classic/#search%7Cgav%7C1%7Cg%3A%22org.hibernate%22%20AND%20a%3Aを追加します%22hibernate-core%22[依存関係]:

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-core</artifactId>
    <version>5.2.8.Final</version>
</dependency>

そして、我々はhttps://search.maven.org/classic/#search%7C1%7Cg%3A%22org.hsqldb%22%20AND%20a%3A%22hsqldb%22[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=?

これは、オブジェクトが変更可能になり(注釈を含めない場合は mutable がデフォルト値になり)、更新によってその機能を実行できるようになるためです。

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__が例外をスローするというもう1つのシナリオでは、削除しようとしたときに__ @ Cascade__アノテーションを設定したときに例外が発生します。

そのため、__ @ Immutable__が存在するときはいつでも、削除しようとします。

[source,java,gutter:,true]

@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(); }

出力:

[source,shell,gutter:,true]

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 アノテーションを探り、それがどのようにしてより良いセマンティクスとデータの制約を定義するのに役立つかを説明します。

いつものように、これらすべての例とスニペットの実装はhttps://github.com/eugenp/tutorials/tree/master/persistence-modules/hibernate5[the GitHub project]にあります。これはMavenベースのプロジェクトなので、インポートして実行するのは簡単なはずです。