Hibernate saveOrUpdate поведение - PullRequest
38 голосов
/ 22 июня 2011

Кто-нибудь знает, как Hibernate знает, ВСТАВИТЬ или ОБНОВИТЬ значение в базе данных, когда вызывается session.saveOrUpdate()?

До сих пор я только определил, что оно не зависит от информации вкеш, и что существование сущности в базе данных определяется первичным ключом.

Ответы [ 5 ]

39 голосов
/ 22 июня 2011

Когда вы используете .saveOrUpdate(), Hibernate проверит, является ли объект временным (у него нет свойства идентификатора), и если это так, он сделает его постоянным, генерируя его идентификатор и назначая его сеансу.Если объект уже имеет идентификатор, он будет выполнять .update().

Из документации :

saveOrUpdate () выполняет следующие действия:

  • если объект уже является постоянным в этом сеансе, ничего не делать
  • , если другой объект, связанный с сеансом, имеет такой же идентификатор, сгенерировать исключение
  • , если у объекта нет свойства идентификатора, сохранить() it
  • , если идентификатор объекта имеет значение, присвоенное вновь созданному объекту, save () it
  • , если объект версионирован с помощью или, и значение свойства version такое жезначение, присвоенное вновь созданному объекту, сохранить (), иначе обновить () объект
9 голосов
/ 03 февраля 2014

Возможно, полезно цитировать библию Hibernate ( Java Persistence с Hibernate, 2-е изд. , стр. 528):

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

Как Hibernate определяет, какие экземпляры являются старыми, а какие новыми?Диапазон вариантов доступен.Hibernate предполагает, что экземпляр является несохраненным временным экземпляром, если:

  • Свойство идентификатора - null.
  • Свойство версии или метки времени (если оно существует) - null.
  • Новый экземпляр того же постоянного класса, созданный внутри Hibernate, имеет те же значения идентификатора базы данных, что и данный экземпляр.
  • Вы предоставляете unsaved-value в документе сопоставления для классаи значение свойства идентификатора совпадает.Атрибут unsaved-value также доступен для элементов отображения версии и метки времени.
  • Данные объекта с таким же значением идентификатора отсутствуют в кэше второго уровня.
  • Вы предоставляете реализацию или org.hibernate.Interceptor и верните Boolean.TRUE из Interceptor.isUnsaved() после проверки экземпляра в вашем коде.
2 голосов
/ 22 июня 2011

Как указано здесь , saveOrUpdate либо сохраняет временный экземпляр путем генерации нового идентификатора, либо обновляет / повторно присоединяет отдельные экземпляры, связанные с его текущим идентификатором.Более конкретно, он делает:

  • , если объект уже является постоянным в этом сеансе, ничего не делать
  • , если другой объект, связанный с сеансом, имеет такой же идентификатор, выдает исключение
  • если у объекта нет свойства идентификатора, save() it
  • , если у идентификатора объекта есть значение, присвоенное вновь созданному объекту, save () it
  • , если объект версионирован<version> или <timestamp>, а значение свойства версии равно
  • тому же значению, присвоенному вновь созданному объекту, save() it
  • в противном случае update() объекту
1 голос
/ 18 июня 2015

Если кто-то не совсем понял в теории, то есть код

MyModel sent = myDao.myDaoImpl(id); 

if(sent == null){                        
    sent = **new MyModel();** // new Object
    sent.setXX(id);
    sent.setYY("Yes");
    sent.setDate(new Date());
    myDao.saveOrUpdate(sent); // Insert will be called
} else if(! "Yes".equalsIgnoreCase(sent.getFlag())) {
    sent.setXX("Yes");
    sent.setDate(new Date());
    myDao.saveOrUpdate(sent); // Update will be called
}
1 голос
/ 22 июня 2011

Это делается на основе значения первичного ключа.Если первичный ключ не определен, его значение по умолчанию будет 0 для числовых суррогатных ключей, и будет выполняться save.Если первичный ключ заполнен, он вызовет update.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...