Какое преимущество persist() vs save() в Hibernate?

Может ли кто-нибудь сказать мне, что преимущество persist() vs save() в Hibernate?

Ответ 1

От этот пост форума

persist() четко определен. Это делает постоянный переходный экземпляр. Однако это не гарантирует, что значение идентификатора будет присвоено постоянный экземпляр немедленно, назначение может произойти при флеше время. В спецификации не сказано, что есть проблема с persist().

persist() также гарантирует, что он не выполнять инструкцию INSERT, если она вызывается вне транзакции границы. Это полезно в длительные разговоры с расширенный контекст сеанса/персистентности.

Требуется метод типа persist().

save() не гарантирует то же самое, он возвращает идентификатор, и если INSERT должен быть выполнен, чтобы получить идентификатор (например, "идентификационный" генератор, не "последовательность" ), этот INSERT случается немедленно, независимо от того, являетесь ли вы внутри или за пределами транзакции. Это не хорошо в долгосрочной перспективе беседа с расширенным Контекст сеанса/персистентности.

Ответ 2

Я провел хорошее исследование save() и persist(), включая запуск его на моей локальной машине несколько раз. Все предыдущие объяснения сбивают с толку и не являются правильными. Я сравнил ниже save() и persist() после тщательного исследования.

Save()

  1. Возвращает сгенерированный идентификатор после сохранения. Его тип возврата Serializable.
  2. Немедленно сохраняет значение в БД и отслеживает сущность до конца сеанса (я пытался изменить значения сущности вне транзакции, это не показывает никакого эффекта при фиксации сеанса)
  3. сохранить изменения в БД вне транзакции.
  4. Назначает сгенерированный идентификатор сущности, которую вы сохраняете
  5. Session.save() для отдельного объекта создаст новую строку в таблице.

Persist()

  1. Не возвращает сгенерированный идентификатор после сохранения. Тип возврата void.
  2. Немедленно сохраняет значение в БД и отслеживает сущность до конца сеанса. (Я пытался изменить значения сущности вне транзакции, это не показывает никакого эффекта при фиксации сеанса)
  3. Не сохраняет изменения в БД вне транзакции.
  4. Назначает generated id сущности, которую вы сохраняете
  5. session.persist() для отсоединенного объекта выдает PersistentObjectException, поскольку это не разрешено.

Все это опробовано/протестировано на Hibernate v4.0.1.

Ответ 3

Я сделал небольшое тестирование, чтобы записать разницу между save() и persist().

Похоже, что оба эти метода ведут себя одинаково при работе с Transient Entity, но отличаются при работе с Detached Entity.

В приведенном ниже примере возьмите EmployeeVehicle как объект с PK как vehicleId, который является сгенерированным значением, а vehicleName - одним из его свойств.

Пример 1: Работа с переходным объектом

Session session = factory.openSession();
session.beginTransaction();
EmployeeVehicle entity = new EmployeeVehicle();
entity.setVehicleName("Honda");
session.save(entity);
// session.persist(entity);
session.getTransaction().commit();
session.close();

Результат:

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 detached
Session 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(), поскольку сохранение должно быть тщательно использовано при работе с объектом Transient.

Важное примечание. В приведенном выше примере объект транспортного средства pk является сгенерированным значением, поэтому при использовании save() для сохранения отдельного объекта hibernate генерирует новый идентификатор для сохранения. Однако, если это pk не является сгенерированным значением, это приводит к нарушению ключевого слова исключения.

Ответ 4

Этот вопрос содержит несколько хороших ответов о различных методах сохранения в Hibernate. Чтобы ответить на ваш вопрос напрямую, с помощью save() оператор insert выполняется немедленно, независимо от состояния транзакции. Он возвращает вставленный ключ, чтобы вы могли сделать что-то вроде этого:

long newKey = session.save(myObj);

Поэтому используйте save(), если вам нужен идентификатор, назначенный постоянному экземпляру немедленно.

С persist() оператор insert выполняется в транзакции, а не обязательно сразу. Это предпочтительнее в большинстве случаев.

Используйте persist(), если вам не нужна вставка, чтобы произойти вне очереди с транзакцией, и вам не нужно возвращать вставленный ключ.

Ответ 5

Вот различия, которые помогут вам получить преимущество от методов сохранения и сохранения:

  • Первая разница между сохранением и сохранением заключается в типе возврата. возвращаемый тип постоянного метода недействителен, в то время как возвращаемый тип сохранения
    Метод - Сериализуемый объект.
  • Метод persist() не гарантирует, что значение идентификатора будет быть немедленно назначенным постоянному состоянию, назначение может произойдет во время сброса.

  • Метод persist() не выполнит запрос вставки, если он вызван за пределами границ транзакции. В то время как метод save() возвращает идентификатор, чтобы запрос вставки выполнялся немедленно, чтобы получить идентификатор, независимо от того, находится ли он внутри или снаружи сделка.

  • Метод persist вызывается вне границ транзакции, это полезно в длительных беседах с расширенной сессией контекст. С другой стороны, метод сохранения не хорош в долгосрочной перспективе разговор с расширенным контекстом сеанса.

  • Пятая разница между сохранением и сохранением метода в Hibernate: Сохранение поддерживается JPA, в то время как сохранение поддерживается только Hibernate.

Вы можете увидеть полный рабочий пример из поста Разница между методами сохранения и сохранения в Hibernate

Ответ 6

save(). Как следует из имени метода, для сохранения объекта в базу данных можно использовать функцию hibernate save(). Мы можем вызывать этот метод вне транзакции. Если мы используем это без транзакции, и у нас есть каскадирование между объектами, тогда только первичный объект будет сохранен, если мы не очистим сеанс.

persist() - Hibernate persist похож на сохранение (с транзакцией) и добавляет объект сущности в постоянный контекст, поэтому отслеживаются дальнейшие изменения. Если свойства объекта будут изменены до того, как транзакция будет выполнена или сеанс будет очищен, он также будет сохранен в базе данных. Кроме того, мы можем использовать метод persist() только в пределах границы транзакции, поэтому он безопасен и заботится о любых каскадных объектах. Наконец, persist не возвращает ничего, поэтому нам нужно использовать сохраненный объект, чтобы получить сгенерированное значение идентификатора.

Ответ 7

Вот разница:

  • сохранить:

    • вернет идентификатор/идентификатор, когда объект будет сохранен в базе данных.
    • также сохранит, когда объект попытается сделать то же самое, открыв новый сеанс после его отсоединения.
  • Упорство:

    • вернет пустоту, когда объект будет сохранен в базе данных.
    • будет вызывать PersistentObjectException при попытке сохранить выделенный файл через новый сеанс.

Ответ 8

Основное правило гласит:

Для сущностей с сгенерированным идентификатором:

save(): немедленно возвращает идентификатор объекта в дополнение к постоянству объекта. Таким образом, запрос вставки запускается немедленно.

persist(): возвращает постоянный объект. Он не обязан немедленно возвращать идентификатор, поэтому он не гарантирует немедленного запуска вставки. Это может немедленно запустить вставку, но это не гарантировано. В некоторых случаях запрос может быть запущен немедленно, в то время как в других он может быть запущен во время сброса сеанса.

Для сущностей с присвоенным идентификатором:

save(): немедленно возвращает идентификатор объекта. Поскольку идентификатор уже назначен объекту до вызова save, поэтому вставка не запускается сразу. Он запускается во время сброса сеанса.

persist(): то же самое, что сохранить. Это также стреляет вставкой во время потока.

Предположим, у нас есть объект, который использует сгенерированный идентификатор следующим образом:

@Entity
@Table(name="USER_DETAILS")
public class UserDetails {
    @Id
    @Column(name = "USER_ID")
    @GeneratedValue(strategy=GenerationType.AUTO)
    private int userId;

    @Column(name = "USER_NAME")
    private String userName;

    public int getUserId() {
        return userId;
    }
    public void setUserId(int userId) {
        this.userId = userId;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
}

save():

    Session session = sessionFactory.openSession();
    session.beginTransaction();
    UserDetails user = new UserDetails();
    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 = new UserDetails();
    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 будет назначен вручную.

@Entity
@Table(name="USER_DETAILS")
public class UserDetails {
    @Id
    @Column(name = "USER_ID")
    private int userId;

    @Column(name = "USER_NAME")
    private String userName;

    public int getUserId() {
        return userId;
    }
    public void setUserId(int userId) {
        this.userId = userId;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
}

для сохранения():

Session session = sessionFactory.openSession();
session.beginTransaction();
UserDetails user = new UserDetails();
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();

для persist():

Session session = sessionFactory.openSession();
session.beginTransaction();
UserDetails user = new UserDetails();
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();

Вышеуказанные случаи были верны, когда сохранение или сохранение вызывались из транзакции.

Другие отличия между сохранением и сохранением:

  1. save() может вызываться вне транзакции. Если назначенный идентификатор используется, то, поскольку идентификатор уже доступен, поэтому запрос вставки не запускается немедленно. Запрос запускается только тогда, когда сеанс сбрасывается.

  2. Если используется сгенерированный идентификатор, то, поскольку id нужно сгенерировать, вставка сразу запускается. Но это только спасает первичную сущность. Если у сущности есть несколько каскадных сущностей, то они не будут сохранены в БД на данный момент. Они будут сохранены при сбросе сессии.

  3. Если функция persist() находится за пределами транзакции, вставка запускается только при сбросе сеанса независимо от того, какой тип идентификатора (сгенерированный или назначенный) используется.

  4. Если сохранение вызывается для постоянного объекта, то объект сохраняется с помощью запроса на обновление.

Ответ 9

На самом деле разница между методами hibernate save() и persist() зависит от используемого класса генератора.
Если наш класс генератора назначен, то нет никакой разницы между методами save() и persist(). Поскольку назначенный генератор означает, что в качестве программиста нам нужно указать значение первичного ключа для сохранения в базе данных справа [Надеюсь, вы знаете эту концепцию генераторов] В случае другого, кроме назначенного класса генератора, предположим, что если наше имя класса генератора является Increment означает, что спящий режим сам присваивает значение идентификатора первичного ключа вправо базы данных [кроме назначенного генератора, спящий режим используется только для того, чтобы заботиться о значении идентификатора первичного ключа помнить ], поэтому в этом случае, если мы будем вызывать метод save() или persist(), он будет вставлять запись в базу данных, как правило, Но слушайте, что метод save() может возвращать значение этого первичного ключа, которое генерируется спящим, и мы можем видеть его с помощью long s = session.save(k);
В этом же случае persist() никогда не даст никакого значения клиенту, верните void.
persist() также гарантирует, что он не будет выполнять инструкцию INSERT, если она вызывается за пределами границ транзакции.
где в качестве Save() INSERT происходит немедленно, независимо от того, находитесь ли вы внутри или вне транзакции.

Ответ 10

Он полностью ответил на основе типа "генератора" в идентификаторе при сохранении любой сущности. Если значение для генератора "назначено", это означает, что вы предоставляете идентификатор. Тогда он не делает различий в спящем режиме для сохранения или сохранения. Вы можете пойти любым способом, который вы хотите. Если значение не "назначено" и вы используете save(), вы получите идентификатор как результат операции save().

Еще одна проверка - выполняете ли вы операцию вне предела транзакции или нет. Потому что persist() принадлежит JPA, а save() для спящего. Поэтому использование persist() вне границ транзакции не позволит это сделать и выдает исключение, связанное с persistant. в то время как с save() такого ограничения нет, и можно выполнить транзакцию с БД через save() вне предела транзакции.