@Immutable im Ruhezustand

@ Im Ruhezustand unveränderlich

1. Überblick

In diesem Artikel wird erläutert, wie wir eine Entität, Sammlung oder ein AttributImmutableim Ruhezustand erstellen können.

Standardmäßig sind Felder veränderbar. Dies bedeutet, dass wir Operationen an ihnen ausführen können, die ihren Status ändern.

2. Maven

Um unser Projekt zum Laufen zu bringen, müssen wir zuerst die erforderlichen Abhängigkeiten zu unserenpom.xmlhinzufügen. Und während wir mit Hibernate arbeiten, werden wir die entsprechendendependency hinzufügen:


    org.hibernate
    hibernate-core
    5.2.8.Final

Und weil wir mitHSQLDB arbeiten, brauchen wir auch:


    org.hsqldb
    hsqldb
    2.3.4

3. Anmerkung zu Entitäten

Definieren wir zunächst eine einfache Entitätsklasse:

@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
}

Wie Sie bemerkt haben, haben wir unserer Entität bereits die Annotation@Immutablehinzugefügt. Wenn wir also versuchen,Eventzu speichern:

@Test
public void addEvent() {
    Event event = new Event();
    event.setId(2L);
    event.setTitle("Public Event");
    session.save(event);
    session.getTransaction().commit();
    session.close();
}

Dann sollten wir die Ausgabe bekommen:

Hibernate: insert into events (title, event_id) values (?, ?)

Die Ausgabe sollte auch dann gleich sein, wenn wir die Anmerkung entfernen. Dies bedeutet, dass es keine Auswirkungen gibt, wenn wir versuchen, eine Entität unabhängig von der Anmerkung hinzuzufügen.

Es ist auch wichtig zu beachten, dass wir in der EntitätEventGeneratedIddie AnnotationGeneratedValuehinzugefügt haben. Dies macht jedoch nur dann einen Unterschied, wenn wir eine Entität erstellen. Dies liegt daran, dass die Generierungsstrategie für die ID angegeben wird. Alle anderen Vorgänge wirken sich aufgrund der Annotation vonImmutablenicht auf das FeldIdaus.

3.1. Aktualisieren der Entität

Jetzt hatten wir kein Problem beim Speichern einer Entität. Versuchen wir, sie zu aktualisieren:

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

Der Ruhezustand ignoriert einfach die Operationupdate, ohne eine Ausnahme auszulösen. Wenn wir jedoch die Annotation@Immutableentfernen, erhalten wir ein anderes Ergebnis:

Hibernate: select ... from events where title='My Event'
Hibernate: update events set title=? where event_id=?

Dies sagt uns, dass unser Objekt jetzt veränderbar ist (mutable ist der Standardwert, wenn wir die Anmerkung nicht einschließen) und dass das Update seine Aufgabe erfüllen kann.

3.2. Entität löschen

Wenn es um das Löschen einer Entität geht:

@Test
public void deleteEvent() {
    Event event = (Event) session.createQuery(
      "FROM Event WHERE title='My Event'").list().get(0);
    session.delete(event);
    session.getTransaction().commit();
}

Wir können den Löschvorgang unabhängig davon durchführen, ob er veränderlich ist oder nicht:

Hibernate: select ... from events where title='My Event'
Hibernate: delete from events where event_id=?

4. Anmerkung zu Sammlungen

Bisher haben wir gesehen, was die Annotation mit Entitäten bewirkt, aber wie eingangs erwähnt, kann sie auch auf Sammlungen angewendet werden.

Fügen wir zunächst unsererEvent-Klasse eine Sammlung hinzu:

@Immutable
public Set getGuestList() {
    return guestList;
}

Wie zuvor haben wir die Anmerkung zuvor hinzugefügt. Wenn wir also versuchen, unserer Sammlung ein Element hinzuzufügen:

org.hibernate.HibernateException:
  changed an immutable collection instance: [com.example.entities.Event.guestList#1]

Dieses Mal erhalten wir eine Ausnahme, da wir bei Sammlungen nicht berechtigt sind, sie hinzuzufügen oder zu löschen.

4.1. Sammlungen löschen

Das andere Szenario, in dem einCollection unveränderlich ist, löst eine Ausnahme aus, wenn wir versuchen zu löschen und die Annotation@Cascadefestgelegt haben.

Immer wenn@Immutable vorhanden ist und wir versuchen zu löschen:

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

Ausgabe:

org.hibernate.HibernateException:
  changed an immutable collection instance:
  [com.example.entities.Event.guestList#1]

5. XML-Hinweise

Schließlich kann die Konfiguration auch mithilfe von XML über das Attributmutable=false erfolgen:


    
        
            
        
        
    

Da wir die Beispiele jedoch im Grunde genommen mit der Annotation-Methode implementiert haben, werden wir mit XML nicht auf Details eingehen.

6. Fazit

In diesem kurzen Artikel untersuchen wir die nützliche Annotation von@Immutableaus dem Ruhezustand und wie dies uns helfen kann, eine bessere Semantik und Einschränkungen für unsere Daten zu definieren.

Wie immer ist die Implementierung all dieser Beispiele und Snippets inthe GitHub project zu finden. Dies ist ein Maven-basiertes Projekt, daher sollte es einfach zu importieren und auszuführen sein.