persist()хорошо определено. Это делает временный экземпляр постоянным. Однако это не гарантирует, что значение идентификатора будет назначено постоянному экземпляру немедленно, назначение может произойти во время сброса. В спецификации это не сказано, с чем у меня проблема persist().
persist()также гарантирует, что он не будет выполнять инструкцию INSERT, если он вызывается вне границ транзакции. Это полезно в длительных беседах с расширенным контекстом сеанса / постоянства.
Такой метод, как persist()требуется.
save()не гарантирует то же самое, он возвращает идентификатор, и если для получения идентификатора необходимо выполнить INSERT (например, генератор «identity», а не «sequence»), эта INSERT происходит немедленно, независимо от того, находитесь вы внутри или снаружи сделка Это не хорошо в длительном разговоре с расширенным контекстом сеанса / постоянства.
добавить еще из того же поста, чтобы скулить: «К сожалению, 5 лет спустя эта ветка все еще остается единственным ясным источником информации по этому вопросу. Документация Hibernate, хотя и многословна, лишена всей информации, кроме самой тривиальной информации об использовании. Почему последний пост Кристиана отсутствует в Javadoc для Session, это просто еще одна загадка документации Hibernate ».
kommradHomer
Вы имеете в виду, что метод persist () переведет сущность в отдельное состояние, а save () - в присоединенное состояние?
рекиныз
2
Недавно я использовал и сохранить, и сохранить в двунаправленном отображении «один ко многим». я обнаружил, что сохранение не распространяется на ребенка, т. е. в таблицу сохраняется / вставляется только родитель. Тем не менее, persist выполнил задачу сохранения родителя и ребенка за один вызов. Я использую составной идентификатор, а не сгенерированный идентификатор.
Арн-Арн
68
Я провел хорошее исследование save () и persist (), включая запуск его на моей локальной машине несколько раз. Все предыдущие объяснения сбивают с толку и не являются правильными. Я сравнил save () и persist () ниже после тщательного исследования.
Save()
Возвращает сгенерированный идентификатор после сохранения. Его Serializableтип возвращаемого значения .
сохранить изменения в БД вне транзакции.
Назначает сгенерированный идентификатор сущности, которую вы сохраняете
Session.save () для отдельного объекта создаст новую строку в таблице.
Persist()
Не возвращает сгенерированный идентификатор после сохранения. Свой тип возврата void.
Не сохраняет изменения в БД вне транзакции.
Назначает generated idсущность, которую вы сохраняете
session.persist()за оторванный объект выбросит так PersistentObjectExceptionкак это не разрешено.
Пункт 3 для Save () и Persist () упоминается, но на самом деле они не совпадают. Метод Persist () также сохраняет изменения в БД вне транзакции.
Рави.Кумар
2
когда я проверял после совершения транзакции, используя постоянный метод, значение не сохраняется в БД
Laxminarayana Challagonda
Итак, № 1 и № 5 - это реальная разница между ними? Если вам нужен возвращенный идентификатор или создана новая строка, используйте Save()?
user2490003
Как Save () # 3 возможен вне транзакции
Викас Сингх
24
Я сделал некоторые издеваться тестирование , чтобы записать разницу между save()иpersist() .
Похоже, что оба этих метода ведут себя одинаково при работе с Transient Entity, но различаются при работе с Detached Entity.
Для приведенного ниже примера возьмите EmployeeVehicle как объект с PK, vehicleIdкоторый является сгенерированным значением и vehicleNameодним из его свойств.
select nextval ('hibernate_sequence')// This is for vehicle Id generated : 36
insert into Employee_Vehicle(Vehicle_Name,Vehicle_Id) values (Honda,36)
Обратите внимание, что результат такой же, когда вы получаете уже сохраненный объект и сохраняете его
EmployeeVehicle entity =(EmployeeVehicle)session.get(EmployeeVehicle.class,36);
entity.setVehicleName("Toyota");
session.save(entity);------->**instead of session.update(entity);**// session.persist(entity);
Повторите то же самое с использованием persist(entity)и получите то же самое с новым Id (скажем, 37, Honda);
Пример 2: работа с отделенным объектом
// Session 1 // Get the previously saved Vehicle Entity Session session = factory.openSession();
session.beginTransaction();EmployeeVehicle entity =(EmployeeVehicle)session.get(EmployeeVehicle.class,36);
session.close();// Session 2// Here in Session 2 , vehicle entity obtained in previous session is a detached object and now we will try to save / persist it // (i) Using Save() to persist a detached object Session session2 = factory.openSession();
session2.beginTransaction();
entity.setVehicleName("Toyota");
session2.save(entity);
session2.getTransaction().commit();
session2.close();
Результат: Вы можете ожидать, что Автомобиль с идентификатором 36, полученным в предыдущей сессии, будет обновлен с именем «Тойота». Но что происходит, так это то, что в БД сохраняется новый объект с новым идентификатором, сгенерированным для и названным как «Тойота»
select nextval ('hibernate_sequence')
insert into Employee_Vehicle(Vehicle_Name,Vehicle_Id) values (Toyota,39)
Использование persist для сохранения отдельного объекта
// (ii) Using Persist() to persist a detached// Session 1 Session session = factory.openSession();
session.beginTransaction();EmployeeVehicle entity =(EmployeeVehicle)session.get(EmployeeVehicle.class,36);
session.close();// Session 2// Here in Session 2 , vehicle entity obtained in previous session is a detached object and now we will try to save / persist it // (i) Using Save() to persist a detachedSession session2 = factory.openSession();
session2.beginTransaction();
entity.setVehicleName("Toyota");
session2.persist(entity);
session2.getTransaction().commit();
session2.close();
Результат:
Exception being thrown : detached entity passed to persist
Таким образом, всегда лучше использовать Persist (), а не Save (), так как save должен быть осторожным при работе с временным объектом.
Важное примечание: в приведенном выше примере pk объекта транспортного средства является сгенерированным значением, поэтому при использовании save () для сохранения отсоединенного объекта hibernate генерирует новый идентификатор для сохранения. Однако, если этот pk не является сгенерированным значением, это приведет к нарушению ключа, указывающего на исключение.
Этот вопрос имеет несколько хороших ответов о различных методах сохранения в Hibernate. Чтобы ответить на ваш вопрос напрямую, с помощью save () оператор вставки выполняется немедленно, независимо от состояния транзакции. Он возвращает вставленный ключ, чтобы вы могли сделать что-то вроде этого:
long newKey = session.save(myObj);
Поэтому используйте save (), если вам нужен идентификатор, назначенный постоянному экземпляру немедленно.
С помощью persist () оператор вставки выполняется в транзакции, а не обязательно сразу. Это предпочтительнее в большинстве случаев.
Используйте persist (), если вам не нужно, чтобы вставка происходила вне последовательности транзакции, и вам не нужен возвращенный вставленный ключ.
Вот различия, которые могут помочь вам понять преимущества методов сохранения и сохранения:
Первое различие между сохранением и сохранением - это тип возвращаемого значения. Возвращаемый тип метода persist - void, а возвращаемый тип
метода save - Serializable object.
Метод persist () не гарантирует, что значение идентификатора будет немедленно присвоено постоянному состоянию, назначение может произойти во время сброса.
Метод persist () не выполнит запрос вставки, если он вызывается вне границ транзакции. В то время как метод save () возвращает идентификатор, так что запрос вставки выполняется немедленно для получения идентификатора, независимо от того, находится ли он внутри или вне транзакции.
Метод persist вызывается вне границ транзакции, он полезен в длительных беседах с расширенным контекстом сеанса. С другой стороны, метод сохранения не годится в длительном диалоге с расширенным контекстом сеанса.
Пятое различие между методом сохранения и сохранением в Hibernate: постоянство поддерживается JPA, в то время как сохранение поддерживается только Hibernate.
Сначала вы говорите: «Метод persist () не выполнит запрос вставки, если он вызывается вне границ транзакции». Затем вы говорите: «Метод persist вызывается вне границ транзакции, он полезен в длительных беседах с расширенным контекстом сеанса». Разве они не противоречат друг другу? Я не понимаю
Кумар Маниш
@KumarManish В случае использования метода persist запрос на вставку выполняется во время сброса. Так что это лучшие практики в длительных разговорах
Дэвид Фам
5
save () - Как следует из названия метода, hibernate save () может использоваться для сохранения объекта в базе данных. Мы можем вызвать этот метод вне транзакции. Если мы используем это без транзакции, и у нас есть каскад между сущностями, то сохраняется только основная сущность, если мы не очистим сеанс.
persist () - Hibernate persist похож на save (с транзакцией) и добавляет объект сущности в постоянный контекст, поэтому любые дальнейшие изменения отслеживаются. Если свойства объекта изменяются до фиксации транзакции или сброса сеанса, он также будет сохранен в базе данных. Кроме того, мы можем использовать метод persist () только в пределах границы транзакции, поэтому он безопасен и заботится о любых каскадных объектах. Наконец, persist ничего не возвращает, поэтому нам нужно использовать постоянный объект, чтобы получить сгенерированное значение идентификатора.
Можете ли вы показать пример с фрагментом. Это было бы полезно.
Avikool91
5
Основное правило гласит:
Для сущностей с сгенерированным идентификатором:
save (): немедленно возвращает идентификатор объекта в дополнение к постоянству объекта. Таким образом, запрос вставки запускается немедленно.
persist (): возвращает постоянный объект. Он не обязан немедленно возвращать идентификатор, поэтому не гарантирует немедленного запуска вставки. Это может немедленно запустить вставку, но это не гарантировано. В некоторых случаях запрос может быть запущен немедленно, а в других - во время сброса сеанса.
Для сущностей с присвоенным идентификатором:
save (): немедленно возвращает идентификатор объекта. Поскольку идентификатор уже назначен объекту до вызова save, поэтому вставка не запускается сразу. Он запускается во время сброса сеанса.
persist (): то же самое, что сохранить. Это также огонь вставки во время промывки.
Предположим, у нас есть объект, который использует сгенерированный идентификатор следующим образом:
Session session = sessionFactory.openSession();
session.beginTransaction();UserDetails user =newUserDetails();
user.setUserName("Gaurav");
session.save(user);// Query is fired immediately as this statement is executed.
session.getTransaction().commit();
session.close();
persist ():
Session session = sessionFactory.openSession();
session.beginTransaction();UserDetails user =newUserDetails();
user.setUserName("Gaurav");
session.persist(user);// Query is not guaranteed to be fired immediately. It may get fired here.
session.getTransaction().commit();// If it not executed in last statement then It is fired here.
session.close();
Теперь предположим, что у нас есть та же сущность, определенная следующим образом, но в поле id не было сгенерировано аннотации, т.е. ID будет назначен вручную.
Session session = sessionFactory.openSession();
session.beginTransaction();UserDetails user =newUserDetails();
user.setUserId(1);
user.setUserName("Gaurav");
session.save(user);// Query is not fired here since id for object being referred by user is already available. No query need to be fired to find it. Data for user now available in first level cache but not in db.
session.getTransaction().commit();// Query will be fired at this point and data for user will now also be available in DB
session.close();
для постоянного ():
Session session = sessionFactory.openSession();
session.beginTransaction();UserDetails user =newUserDetails();
user.setUserId(1);
user.setUserName("Gaurav");
session.persist(user);// Query is not fired here.Object is made persistent. Data for user now available in first level cache but not in db.
session.getTransaction().commit();// Query will be fired at this point and data for user will now also be available in DB
session.close();
Вышеуказанные случаи были верны, когда save или persist вызывались из транзакции.
Другие отличия между сохранением и сохранением:
save () может вызываться вне транзакции. Если назначенный идентификатор используется, то, поскольку идентификатор уже доступен, поэтому запрос вставки не запускается немедленно. Запрос запускается только тогда, когда сеанс сбрасывается.
Если используется сгенерированный идентификатор, то, поскольку id нужно сгенерировать, вставка сразу запускается. Но это только спасает первичную сущность. Если у сущности есть несколько каскадных сущностей, то они не будут сохранены в БД на данный момент. Они будут сохранены, когда сессия сброшена.
Если persist () находится за пределами транзакции, вставка запускается только при сбросе сеанса независимо от того, какой тип идентификатора (сгенерированный или назначенный) используется.
Если сохранение вызывается для постоянного объекта, то объект сохраняется с помощью запроса на обновление.
На самом деле, разница между методами hibernate save () и persist () зависит от класса генератора, который мы используем.
Но здесь дело в том, что метод save () может возвращать значение идентификатора первичного ключа, сгенерированное hibernate, и мы можем увидеть его по
длинным s = session.save (k);
В этом же случае, persist () никогда не вернет клиенту никакого значения, тип возврата void.
Функция persist () также гарантирует, что она не выполнит инструкцию INSERT, если она вызывается вне границ транзакции.
тогда как в save () INSERT происходит немедленно, независимо от того, находитесь ли вы внутри или вне транзакции.
Если наш класс генератора назначен, то нет никакой разницы между методами save () и persist (). Поскольку генератор «назначен» означает, что как программисту нам нужно дать значение первичного ключа для сохранения в праве на базу данных [Надеюсь, вы знакомы с этой концепцией генераторов] В случае, если класс генератора не назначен, предположим, что имя нашего класса генератора равно «Приращение» означает hibernate сам назначит значение идентификатора первичного ключа в праве базы данных [кроме назначенного генератора, hibernate используется только для обеспечения запоминания значения идентификатора первичного ключа], поэтому в этом случае, если мы вызовем метод save () или persist (), тогда он вставит запись в базу данных в обычном режиме.
Он полностью ответил на основе типа «генератора» в идентификаторе при сохранении любой сущности. Если значение для генератора «назначено», это означает, что вы предоставляете идентификатор. Тогда он не делает различий в спящем режиме для сохранения или сохранения. Вы можете пойти любым способом, который вы хотите. Если значение не «назначено» и вы используете save (), вы получите идентификатор в качестве возврата из операции save ().
Другая проверка заключается в том, выполняете ли вы операцию вне предела транзакции или нет. Потому что persist () принадлежит JPA, а save () для спящего. Поэтому использование persist () вне границ транзакции не позволит сделать это и выдает исключение, связанное с persistant. в то время как с save () такого ограничения нет, и можно выполнить транзакцию с БД через save () вне предела транзакции.
Ответы:
Из этого сообщения на форуме
источник
Я провел хорошее исследование save () и persist (), включая запуск его на моей локальной машине несколько раз. Все предыдущие объяснения сбивают с толку и не являются правильными. Я сравнил save () и persist () ниже после тщательного исследования.
Save()
Serializable
тип возвращаемого значения .Persist()
generated id
сущность, которую вы сохраняетеsession.persist()
за оторванный объект выбросит такPersistentObjectException
как это не разрешено.Все это проверено / опробовано
Hibernate v4.0.1
.источник
Save()
?Я сделал некоторые издеваться тестирование , чтобы записать разницу между
save()
иpersist()
.Похоже, что оба этих метода ведут себя одинаково при работе с Transient Entity, но различаются при работе с Detached Entity.
Для приведенного ниже примера возьмите EmployeeVehicle как объект с PK,
vehicleId
который является сгенерированным значением иvehicleName
одним из его свойств.Пример 1. Работа с временным объектом
Результат:
Обратите внимание, что результат такой же, когда вы получаете уже сохраненный объект и сохраняете его
Повторите то же самое с использованием
persist(entity)
и получите то же самое с новым Id (скажем, 37, Honda);Пример 2: работа с отделенным объектом
Результат: Вы можете ожидать, что Автомобиль с идентификатором 36, полученным в предыдущей сессии, будет обновлен с именем «Тойота». Но что происходит, так это то, что в БД сохраняется новый объект с новым идентификатором, сгенерированным для и названным как «Тойота»
Использование persist для сохранения отдельного объекта
Результат:
Таким образом, всегда лучше использовать Persist (), а не Save (), так как save должен быть осторожным при работе с временным объектом.
Важное примечание: в приведенном выше примере pk объекта транспортного средства является сгенерированным значением, поэтому при использовании save () для сохранения отсоединенного объекта hibernate генерирует новый идентификатор для сохранения. Однако, если этот pk не является сгенерированным значением, это приведет к нарушению ключа, указывающего на исключение.
источник
Этот вопрос имеет несколько хороших ответов о различных методах сохранения в Hibernate. Чтобы ответить на ваш вопрос напрямую, с помощью save () оператор вставки выполняется немедленно, независимо от состояния транзакции. Он возвращает вставленный ключ, чтобы вы могли сделать что-то вроде этого:
Поэтому используйте save (), если вам нужен идентификатор, назначенный постоянному экземпляру немедленно.
С помощью persist () оператор вставки выполняется в транзакции, а не обязательно сразу. Это предпочтительнее в большинстве случаев.
Используйте persist (), если вам не нужно, чтобы вставка происходила вне последовательности транзакции, и вам не нужен возвращенный вставленный ключ.
источник
Вот различия, которые могут помочь вам понять преимущества методов сохранения и сохранения:
метода save - Serializable object.
Метод persist () не гарантирует, что значение идентификатора будет немедленно присвоено постоянному состоянию, назначение может произойти во время сброса.
Метод persist () не выполнит запрос вставки, если он вызывается вне границ транзакции. В то время как метод save () возвращает идентификатор, так что запрос вставки выполняется немедленно для получения идентификатора, независимо от того, находится ли он внутри или вне транзакции.
Метод persist вызывается вне границ транзакции, он полезен в длительных беседах с расширенным контекстом сеанса. С другой стороны, метод сохранения не годится в длительном диалоге с расширенным контекстом сеанса.
Пятое различие между методом сохранения и сохранением в Hibernate: постоянство поддерживается JPA, в то время как сохранение поддерживается только Hibernate.
Вы можете увидеть полный рабочий пример из поста Разница между сохранением и сохранением метода в Hibernate
источник
save () - Как следует из названия метода, hibernate save () может использоваться для сохранения объекта в базе данных. Мы можем вызвать этот метод вне транзакции. Если мы используем это без транзакции, и у нас есть каскад между сущностями, то сохраняется только основная сущность, если мы не очистим сеанс.
persist () - Hibernate persist похож на save (с транзакцией) и добавляет объект сущности в постоянный контекст, поэтому любые дальнейшие изменения отслеживаются. Если свойства объекта изменяются до фиксации транзакции или сброса сеанса, он также будет сохранен в базе данных. Кроме того, мы можем использовать метод persist () только в пределах границы транзакции, поэтому он безопасен и заботится о любых каскадных объектах. Наконец, persist ничего не возвращает, поэтому нам нужно использовать постоянный объект, чтобы получить сгенерированное значение идентификатора.
источник
Вот разница:
спасти:
Упорство:
источник
Основное правило гласит:
Для сущностей с сгенерированным идентификатором:
save (): немедленно возвращает идентификатор объекта в дополнение к постоянству объекта. Таким образом, запрос вставки запускается немедленно.
persist (): возвращает постоянный объект. Он не обязан немедленно возвращать идентификатор, поэтому не гарантирует немедленного запуска вставки. Это может немедленно запустить вставку, но это не гарантировано. В некоторых случаях запрос может быть запущен немедленно, а в других - во время сброса сеанса.
Для сущностей с присвоенным идентификатором:
save (): немедленно возвращает идентификатор объекта. Поскольку идентификатор уже назначен объекту до вызова save, поэтому вставка не запускается сразу. Он запускается во время сброса сеанса.
persist (): то же самое, что сохранить. Это также огонь вставки во время промывки.
Предположим, у нас есть объект, который использует сгенерированный идентификатор следующим образом:
спасти() :
persist ():
Теперь предположим, что у нас есть та же сущность, определенная следующим образом, но в поле id не было сгенерировано аннотации, т.е. ID будет назначен вручную.
для сохранения ():
для постоянного ():
Вышеуказанные случаи были верны, когда save или persist вызывались из транзакции.
Другие отличия между сохранением и сохранением:
save () может вызываться вне транзакции. Если назначенный идентификатор используется, то, поскольку идентификатор уже доступен, поэтому запрос вставки не запускается немедленно. Запрос запускается только тогда, когда сеанс сбрасывается.
Если используется сгенерированный идентификатор, то, поскольку id нужно сгенерировать, вставка сразу запускается. Но это только спасает первичную сущность. Если у сущности есть несколько каскадных сущностей, то они не будут сохранены в БД на данный момент. Они будут сохранены, когда сессия сброшена.
Если persist () находится за пределами транзакции, вставка запускается только при сбросе сеанса независимо от того, какой тип идентификатора (сгенерированный или назначенный) используется.
Если сохранение вызывается для постоянного объекта, то объект сохраняется с помощью запроса на обновление.
источник
На самом деле, разница между методами hibernate save () и persist () зависит от класса генератора, который мы используем. Но здесь дело в том, что метод save () может возвращать значение идентификатора первичного ключа, сгенерированное hibernate, и мы можем увидеть его по длинным s = session.save (k); В этом же случае, persist () никогда не вернет клиенту никакого значения, тип возврата void. Функция persist () также гарантирует, что она не выполнит инструкцию INSERT, если она вызывается вне границ транзакции. тогда как в save () INSERT происходит немедленно, независимо от того, находитесь ли вы внутри или вне транзакции.
Если наш класс генератора назначен, то нет никакой разницы между методами save () и persist (). Поскольку генератор «назначен» означает, что как программисту нам нужно дать значение первичного ключа для сохранения в праве на базу данных [Надеюсь, вы знакомы с этой концепцией генераторов] В случае, если класс генератора не назначен, предположим, что имя нашего класса генератора равно «Приращение» означает hibernate сам назначит значение идентификатора первичного ключа в праве базы данных [кроме назначенного генератора, hibernate используется только для обеспечения запоминания значения идентификатора первичного ключа], поэтому в этом случае, если мы вызовем метод save () или persist (), тогда он вставит запись в базу данных в обычном режиме.
источник
Он полностью ответил на основе типа «генератора» в идентификаторе при сохранении любой сущности. Если значение для генератора «назначено», это означает, что вы предоставляете идентификатор. Тогда он не делает различий в спящем режиме для сохранения или сохранения. Вы можете пойти любым способом, который вы хотите. Если значение не «назначено» и вы используете save (), вы получите идентификатор в качестве возврата из операции save ().
Другая проверка заключается в том, выполняете ли вы операцию вне предела транзакции или нет. Потому что persist () принадлежит JPA, а save () для спящего. Поэтому использование persist () вне границ транзакции не позволит сделать это и выдает исключение, связанное с persistant. в то время как с save () такого ограничения нет, и можно выполнить транзакцию с БД через save () вне предела транзакции.
источник