Каковы различия между различными методами сохранения в Hibernate?

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

Методы, которые я определил до сих пор:

  • save()
  • update()
  • saveOrUpdate()
  • saveOrUpdateCopy()
  • merge()
  • persist()

    8 Solutions collect form web for “Каковы различия между различными методами сохранения в Hibernate?”

    Вот мое понимание методов. В основном они основаны на API, хотя я не использую их все на практике.

    saveOrUpdate Вызывает либо сохранение, либо обновление в зависимости от некоторых проверок. Например, если идентификатор не существует, вызывается save. В противном случае вызывается обновление.

    save Сохраняет сущность. Будет присвоен идентификатор, если он не существует. Если это так, то это по сути делает обновление. Возвращает сгенерированный идентификатор объекта.

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

    saveOrUpdateCopy Это устарело и больше не должно использоваться. Вместо этого есть …

    merge Теперь это то, где мои знания начинают дрожать. Здесь важна разница между временными, отдельными и постоянными объектами. Подробнее о состояниях объектов см . Здесь . С сохранением и обновлением вы имеете дело с постоянными объектами. Они связаны с сеансом, поэтому Hibernate знает, что изменилось. Но когда у вас есть переходный объект, сеанс отсутствует. В этих случаях вам нужно использовать слияние для обновлений и сохраняться для сохранения.

    persist Как упоминалось выше, это используется для переходных объектов. Он не возвращает сгенерированный идентификатор.

     ╔══════════════╦═══════════════════════════════╦════════════════════════════════╗ ║ METHOD ║ TRANSIENT ║ DETACHED ║ ╠══════════════╬═══════════════════════════════╬════════════════════════════════╣ ║ ║ sets id if doesn't ║ sets new id even if object ║ ║ save() ║ exist, persists to db, ║ already has it, persists ║ ║ ║ returns attached object ║ to DB, returns attached object ║ ╠══════════════╬═══════════════════════════════╬════════════════════════════════╣ ║ ║ sets id on object ║ throws ║ ║ persist() ║ persists object to DB ║ PersistenceException ║ ║ ║ ║ ║ ╠══════════════╬═══════════════════════════════╬════════════════════════════════╣ ║ ║ ║ ║ ║ update() ║ Exception ║ persists and reattaches ║ ║ ║ ║ ║ ╠══════════════╬═══════════════════════════════╬════════════════════════════════╣ ║ ║ copy the state of object in ║ copy the state of obj in ║ ║ merge() ║ DB, doesn't attach it, ║ DB, doesn't attach it, ║ ║ ║ returns attached object ║ returns attached object ║ ╠══════════════╬═══════════════════════════════╬════════════════════════════════╣ ║ ║ ║ ║ ║saveOrUpdate()║ as save() ║ as update() ║ ║ ║ ║ ║ ╚══════════════╩═══════════════════════════════╩════════════════════════════════╝ 
    • См. Форум Hibernate для объяснения тонких различий между сохранением и сохранением. Похоже, разница заключается в том, что оператор INSERT в конечном счете выполняется. Поскольку save возвращает идентификатор, оператор INSERT должен быть выполнен мгновенно независимо от состояния транзакции (что обычно плохо). Persist не будет выполнять какие-либо заявления за пределами текущей транзакции только для назначения идентификатора. Сохранить / Персистировать как работу с временными экземплярами , т. Е. Экземпляры , которые еще не присвоены идентификатором, и как таковые не сохраняются в БД.

    • Обновление и слияние работают как с отдельными экземплярами , так и с экземплярами, которые имеют соответствующую запись в БД, но которые в настоящее время не привязаны (или управляются) сеансом. Разница между ними – это то, что происходит с экземпляром, который передается функции. update пытается повторно привязать экземпляр, это означает, что в противном случае не может быть другого экземпляра постоянного объекта, прикрепленного к сеансу, иначе в противном случае возникает исключение. merge , однако, просто копирует все значения в постоянный экземпляр сеанса (который будет загружен, если он не загружен в настоящий момент). Объект ввода не изменяется. Таким образом, объединение более общее, чем обновление , но может использовать больше ресурсов.

    Эта ссылка хорошо объясняет:

    http://www.stevideter.com/2008/12/07/saveorupdate-versus-merge-in-hibernate/

    У всех нас есть те проблемы, с которыми мы сталкиваемся достаточно редко, что, увидев их снова, мы знаем, что мы решили это, но не можем вспомнить, как это сделать.

    Исключение NonUniqueObjectException, возникающее при использовании Session.saveOrUpdate () в Hibernate, является одним из моих. Я добавлю новые функции в сложное приложение. Все мои модульные тесты работают нормально. Затем при тестировании пользовательского интерфейса, пытаясь сохранить объект, я начинаю получать исключение с сообщением «другой объект с тем же значением идентификатора уже был связан с сеансом». Вот пример кода Java Persistence with Hibernate.

      Session session = sessionFactory1.openSession(); Transaction tx = session.beginTransaction(); Item item = (Item) session.get(Item.class, new Long(1234)); tx.commit(); session.close(); // end of first session, item is detached item.getId(); // The database identity is "1234" item.setDescription("my new description"); Session session2 = sessionFactory.openSession(); Transaction tx2 = session2.beginTransaction(); Item item2 = (Item) session2.get(Item.class, new Long(1234)); session2.update(item); // Throws NonUniqueObjectException tx2.commit(); session2.close(); 

    Чтобы понять причину этого исключения, важно понимать отдельные объекты и что происходит, когда вы вызываете saveOrUpdate () (или просто update ()) для отдельного объекта.

    Когда мы закрываем отдельный сеанс Hibernate, постоянные объекты, с которыми мы работаем, отсоединяются. Это означает, что данные все еще находятся в памяти приложения, но Hibernate больше не отвечает за отслеживание изменений объектов.

    Если мы затем модифицируем наш отдельный объект и хотим его обновить, мы должны снова привязать объект. Во время процесса повторной привязки Hibernate проверит, есть ли другие копии одного и того же объекта. Если он найдет что-либо, он должен сказать нам, что он не знает, что такое «настоящая» копия. Возможно, другие изменения были внесены в другие копии, которые мы ожидаем сохранить, но Hibernate не знает о них, потому что в то время они не управляли ими.

    Вместо того, чтобы сохранять, возможно, плохие данные, Hibernate сообщает нам о проблеме с помощью исключения NonUniqueObjectException.

    Так что нам делать? В Hibernate 3 у нас есть merge () (в Hibernate 2, используйте saveOrUpdateCopy ()). Этот метод заставит Hibernate скопировать любые изменения из других отдельных экземпляров в экземпляр, который вы хотите сохранить, и, таким образом, слияние всех изменений в памяти перед сохранением.

      Session session = sessionFactory1.openSession(); Transaction tx = session.beginTransaction(); Item item = (Item) session.get(Item.class, new Long(1234)); tx.commit(); session.close(); // end of first session, item is detached item.getId(); // The database identity is "1234" item.setDescription("my new description"); Session session2 = sessionFactory.openSession(); Transaction tx2 = session2.beginTransaction(); Item item2 = (Item) session2.get(Item.class, new Long(1234)); Item item3 = session2.merge(item); // Success! tx2.commit(); session2.close(); 

    Важно отметить, что merge возвращает ссылку на недавно обновленную версию экземпляра. Это не повторное подключение к сессии. Если вы проверите, например, равенство (item == item3), вы обнаружите, что в этом случае он возвращает false. Вероятно, вам захочется работать с item3 с этого момента.

    Также важно отметить, что Java Persistence API (JPA) не имеет концепции отсоединенных и повторно подключенных объектов и использует EntityManager.persist () и EntityManager.merge ().

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

    Где вы столкнулись с этой проблемой? Работали ли слияния для вас или вам понадобилось другое решение? Вы предпочитаете всегда использовать слияние или предпочитаете использовать его только по мере необходимости для конкретных случаев

    На самом деле разница между методами hibernate save() и persist() зависит от используемого classа генератора.

    Если наш class генератора назначен, то нет никакой разницы между методами save() и persist( ). Поскольку генератор «назначается» означает, что в качестве программиста нам нужно указать значение первичного ключа для сохранения в базе данных справа [Надеюсь, вы знаете концепцию генераторов]. В случае другого, кроме назначенного classа генератора, предположим, что если наше имя classа генератора является средством Приращения hibernate it self назначит значение идентификатора первичного ключа в правую базу данных [кроме назначенного генератора, hibernate используется только для того, чтобы запомнить значение идентификатора первичного ключа), поэтому в этом случае, если мы вызываем метод save() или persist() тогда он будет вставлять запись в базу данных нормально. Но слышите, что метод save() может вернуть значение первичного ключа, которое генерируется спящим режимом, и мы можем видеть его

     long s = session.save(k); 

    В этом же случае persist() никогда не даст какой-либо ценности клиенту.

    Я нашел хороший пример, показывающий различия между всеми методами сохранения в спящем режиме:

    http://www.journaldev.com/3481/hibernate-session-merge-vs-update-save-saveorupdate-persist-example

    Вкратце, согласно приведенной выше ссылке:

    спасти()

    • Мы можем вызывать этот метод вне транзакции. Если мы используем это без транзакции, и у нас есть каскадирование между сущностями, тогда только первичный объект будет сохранен, если мы не очистим сеанс.
    • Таким образом, если есть другие объекты, сопоставленные с основным объектом, они сохраняются во время совершения транзакции или когда мы очищаем сеанс.

    сохраняются ()

    • Это похоже на использование save () в транзакции, поэтому оно безопасно и заботится о любых каскадных объектах.

    saveOrUpdate ()

    • Может использоваться с транзакцией или без нее, и точно так же, как save (), если она используется без транзакции, отображаемые объекты не будут сохранены un; ess мы очищаем сеанс.

    • Результаты вставлять или обновлять запросы на основе предоставленных данных. Если данные присутствуют в базе данных, выполняется запрос обновления.

    Обновить()

    • Обновление Hibernate должно использоваться там, где мы знаем, что мы только обновляем информацию о сущности. Эта операция добавляет объект сущности в постоянный контекст, и дальнейшие изменения отслеживаются и сохраняются при совершении транзакции.
    • Следовательно, даже после вызова обновления, если мы установим любые значения в сущности, они будут обновляться при совершении транзакции.

    слияния ()

    • Слияние Hibernate можно использовать для обновления существующих значений, однако этот метод создает копию из переданного объекта сущности и возвращает его. Возвращаемый объект является частью постоянного контекста и отслеживается для любых изменений, передаваемый объект не отслеживается. Это основное отличие от merge () от всех других методов.

    Также для практических примеров всех этих вопросов, пожалуйста, обратитесь к ссылке, о которой я упоминал выше, она показывает примеры для всех этих различных методов.

    Имейте в виду, что если вы вызываете обновление для отдельного объекта, всегда будет сделано обновление в базе данных, измените ли вы объект или нет. Если это не то, что вы хотите, вы должны использовать Session.lock () с LockMode.None.

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

    Ни один из следующих ответов не прав. Все эти методы кажутся похожими, но на практике делают совершенно разные вещи. Трудно дать короткие комментарии. Лучше дать ссылку на полную документацию об этих методах: http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/objectstate.html

    Interesting Posts

    Блокировать URL-адрес на уровне браузера

    Отправляйте SMS до тех пор,

    Как сделать целое число log2 () в C ++?

    Могу ли я контролировать, кто использует мой Mac OS X Internet Sharing?

    Linux / Unix в Windows

    В чем разница между портом и сокетом?

    Ошибка, связанная с внутренним classом View в макете / main.xml

    Дизайн Android EditText, чтобы отобразить сообщение об ошибке, как описано в Google

    Таблица сводных таблиц Excel – как сортировать строки как числа

    Резервное копирование DHCP и фильтрация MAC-адресов. Являются ли они одинаковой ценностью?

    В чем разница между «STL» и «C ++ Standard Library»?

    Как я могу обойти «ошибку 0x80070522» при создании файлов в корневом каталоге диска C (C: \)?

    Есть ли ярлык Win7 для позиционирования мыши в центре основного экрана?

    У меня есть как кабель, так и DSL дома. Как я могу это использовать?

    При запуске X удаленно через Cygwin, почему мои шрифты уродливые

    Давайте будем гением компьютера.