@ Неизменный в Hibernate

@ Неизменный в спящем

1. обзор

В этой статье мы поговорим о том, как создать объект, коллекцию или атрибутImmutable в Hibernate.

По умолчанию поля являются изменяемыми, что означает, что мы можем выполнять с ними операции, которые изменяют их состояние.

2. специалист

Чтобы запустить наш проект, нам сначала нужно добавить необходимые зависимости в нашpom.xml. И поскольку мы работаем с Hibernate, мы собираемся добавить соответствующиеdependency:


    org.hibernate
    hibernate-core
    5.2.8.Final

И, поскольку мы работаем сHSQLDB, нам также понадобятся:


    org.hsqldb
    hsqldb
    2.3.4

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.

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 getGuestList() {
    return guestList;
}

Как и раньше, мы добавили аннотацию заранее, поэтому, если мы продолжим и попробуем добавить элемент в нашу коллекцию:

org.hibernate.HibernateException:
  changed an immutable collection instance: [com.example.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.example.entities.Event.guestList#1]

5. XML-заметки

Наконец, конфигурацию также можно выполнить с помощью XML через атрибутmutable=false:


    
        
            
        
        
    

Однако, поскольку мы в основном реализовали примеры, используя метод аннотации, мы не будем вдаваться в детали, используя XML.

6. Заключение

В этой быстрой статье мы исследуем полезную аннотацию@Immutable вне Hibernate и то, как это может помочь нам определить лучшую семантику и ограничения для наших данных.

Как всегда, реализацию всех этих примеров и фрагментов можно найти вthe GitHub project. Это проект на основе Maven, поэтому его легко импортировать и запускать.