Возможные варианты статуса объекта
Как ты уже наверное обратил внимание, когда объект присоединен к Hibernate, его состояние называется Persistent или Managed. Как правильно? Persist или Managed?
Можно и так, и так. Согласно спецификации JPA объект имеет статус Persist, а согласно спецификации Hibernate его состояние называется Managed.
В Hibernate работа с базой ведется через объект типа org.hibernate.Session. Согласно же JPA класс должен называться javax.persistence.EntityManager. На самом деле большой проблемы тут нет, так как оба типа являются интерфейсами.
Интерфейс org.hibernate.Session объявлен так:
interface Session extends java.lang.AutoCloseable, javax.persistence.EntityManager, HibernateEntityManager, QueryProducer, java.io.Serializable, SharedSessionContract {
}
Поэтому в интерфейсе Session есть все методы, которые есть в интерфейсе EntityManager. Но также есть и свои, которые достались ему от более ранних версий Hibernate, когда еще не было спецификации JPA.
Описывается эта вся ситуация вот такой картинкой:
Давай же разберем все методы, которые есть у интерфейса session, а также нюансы их работы.
Нюансы работы метода persist()
При сохранении объекта в базу данных тебе нужно помнить две вещи.
Во-первых, сохранение объекта в итоге приведет к выполнению одной из команд SQL: INSERT или UPDATE. Во-вторых, эти действия произойдут не сразу после вызова метода объекта session, а только после закрытия транзакции.
Давай рассмотрим какую-нибудь простую ситуацию, например, у тебя есть класс User:
@Entity
public class User {
@Id
@GeneratedValue
public Integer id;
@Columnt(name=”user_name”)
public String name;
}
Давай сохраним в базу его объект с помощью метода persist().
User user = new User();
user.setName("Колян");
session.persist(user);
Задача этого метода сохранить в базу данных новый объект. Если такого объекта еще нет, то он будет добавлен в базу через вызов SQL-метода INSERT.
Если же объект уже есть в базе, то ничего не произойдет. Однако возможет еще и третий случай – попытка сохранить в базу объект со статусом Detached. В этом случае кинется исключение. Пример:
User user = new User();
user.setName("Колян");
session.persist(user);
session.evict(user); // отсоединяем объект от сессии
session.persist(user); // тут кинется исключение PersistenceException!
Нюансы работы метода save()
Метод save() достался нынешнему Hibernate от его предыдущих версий. По своей сути он очень похож на метод persist(), он тоже добавляет новую запись в таблицу с помощью метода INSERT. Однако у него есть несколько интересных нюансов.
Во-первых, этот метод возвращает значение – новое ID объекта. Как ты уже знаешь, обычно до добавления в базу у объектов нет ID и оно присваивается уже базой данных. Так вот, метод save() объекта session возвращает ID, которая была присвоена сохраняемому объекту.
Важно! Согласно спецификации Hibernate ID может быть любой сериализуемый объект, не только число. Это может быть строка, число, enum, вообще что угодно, что можно целиком положить в одну колонку таблицы в базе.
Метод save() имеет тип результата Serialized, поэтому его результат нужно приводить к правильному типу:
User user = new User();
user.setName("Колян");
Integer id = (Integer) session.save(user);
Также у метода save() другое поведение в случае с Detached состоянием объекта. Такой объект он рассматривает как новый и просто добавляет еще одну запись:
User user = new User();
user.setName("Колян");
Integer id = (Integer) session.save(user);
session.evict(user); // отсоединяем объект от сессии
Integer id2 = (Integer) session.save(user);
Переменные id и id2 будут отличаться. В таблице в базе данных будут добавлены две записи: по одной для каждой операции save().
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ