JavaRush /Курсы /Модуль 4. Работа с БД /Как сохранить объект в Hibernate

Как сохранить объект в Hibernate

Модуль 4. Работа с БД
11 уровень , 1 лекция
Открыта

Возможные варианты статуса объекта

Как ты уже наверное обратил внимание, когда объект присоединен к 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().

1
Задача
Модуль 4. Работа с БД, 11 уровень, 1 лекция
Недоступна
task1101
Сохрани созданный объект в БД (используй метод save)...
Комментарии (17)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Андрей Уровень 106
4 июня 2025
В Hibernate 7.0.0 Final метод Session.save() был полностью удалён из API. Это означает, что попытки его использования приведут к ошибкам компиляции, и IntelliJ IDEA будет подсвечивать его как недоступный. Ранее этот метод был помечен как устаревший в версии Hibernate 6.0, а начиная с версии 7.0 — полностью исключён из интерфейса Session Вместо метода save() рекомендуется использовать persist(). Однако следует учитывать, что persist() не возвращает идентификатор сущности. Если вам необходимо получить ID после сохранения, вы можете воспользоваться методом getId() вашей сущности, при условии, что ID генерируется автоматически.
СтудентJava Уровень 109
14 февраля 2025
не понимаю, в задачи написано что бы выводилось folse но выводится у меня true и решение проходит
СтудентJava Уровень 109
14 февраля 2025
Разобрался почему выводится true. У меня нет подключение к реальной базе данных MySQL. Поэтому когда я в id1 записываю animal и он присваивает ему номер 1 затем после вызова evict удаляет объект animal из кэша сессии то в id2 он снова присваивает 1. Так как нет подключения к какой либо СУБД
Руслан Никитин Уровень 109
1 февраля 2025
Во-первых, сохранение объекта в итоге приведет к выполнению одной из команд SQL: INSERT или UPDATE - для чего это помещено в описании метода persist() ? UPDATE и persist() как связаны? 😒
Олег Уровень 106 Expert
12 октября 2024
Всё понял.
Роман Уровень 88
11 января 2025
красавец
Дмитрий Уровень 37
16 марта 2024
Еще бы хотелось пояснить по поводу id. Если они генерятся на стороне бд и мы вызвали методы save, а транзакция не закончена, хибернейт в этот момент запросов в бд не делает, а id готов вернуть, как?
Дмитрий Уровень 37
16 марта 2024
Если быть точным, то изменения будут отправлены в бд не после закрытия транзакции, а в момент ее закрытия. То есть новая транзакция создана не будет и запросы улетят в бд в рамках той же транзакции в которой и работали
Дмитрий Уровень 37
16 марта 2024
Требуется нормальный комментарий к схеме "Detached object"! Из не вообще не понятно, что автор пытается донести. Что объект не имеет статус persist, если не был получен из базы, а только крутится в сессии?
Mila Уровень 102
12 января 2024
Когда мы первый раз сохраняем объект animal, мы получаем его идентификатор. После исключения методом evict объекта из сессии, Hibernate этот объект больше не отслеживает. Затем мы снова сохраняем тот же объект, но т.к он ранее был исключен из сессии, Hibernate присваивает ему новый идентификатор. При сравнении должно возвращать false, тк объект был сохранен дважды как два разных экземпляра. Почему возвращает true? Потому что таблицы animal_table нет в схеме. Hibernate не может сохранить объект из-за ошибки, он не присваивает новый id сущности. id1 и id2 были объявлены, но не инициализированы. В случае отсутствия инициализации они получают значение по умолчанию, т.е 0. После неудавшихся попыток сохранения обе переменные = 0. Чтобы исправить ситуацию, можно создать таблицу с помощью properties.put(Environment.HBM2DDL_AUTO, "update") - это автоматически создаст таблицу в соответствии с аннотациями. Также поменять диалект properties.put(Environment.DIALECT, "org.hibernate.dialect.MySQL5Dialect");
Max Dudin Уровень 6 Expert
5 октября 2023
на 05.10.2023 ситуация такая.... они равны ...вы ход true =))) (они равны и в референсном решении) =))) но валидацию задача проходит на ура с зачтение пункта "значение id1 и id2 должны быть разные" прикольно, но всё таки почему они одинаковые?
Дмитрий Уровень 111 Expert
26 октября 2023
На 27.10.23 разные.
Алексей Уровень 1 Expert
12 декабря 2023
12.12.23 true
Павел Уровень 19 Expert
21 марта 2024
Не надо смотреть на дату. Смотрите на сообщения консоли Хибернейта. Мне пришлось вручную сохранять две таблицы через консоль mysql.

create table test.animal_table
(
    id int,
    name varchar(30),
    age int,
    family varchar(30)
);
create table test.animal_table_SEQ
(
    next_val int
);
тогда получится так Это я как слабо разбирающийся в Хибернейт говорю.
Ольга Уровень 108 Expert
6 сентября 2023
И с этой задачей что-то не так. Даже при тотальном копировании правильного ответа задача не принимается с ошибкой, что id у вас не отличаются (3 пункт проверки). Надо бы задачи этого раздела все пересмотреть, кучность косяков возрастает.