JPA слияния против сохранения - PullRequest
66 голосов
/ 12 декабря 2011

До сих пор я предпочитал всегда использовать EntityManager merge(), как для вставки, так и для обновления. Но я также заметил, что слияние выполняет дополнительные запросы выбора перед обновлением / вставкой, чтобы гарантировать, что запись еще не существует в базе данных.

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

Ответы [ 3 ]

69 голосов
/ 12 декабря 2011

Не очень хорошая идея использовать merge, когда достаточно persist - merge выполняет гораздо больше работы.Эта тема обсуждалась ранее в StackOverflow , а эта статья подробно объясняет различия, с некоторыми хорошими схемами, чтобы прояснить ситуацию.

9 голосов
/ 12 декабря 2011

Я бы определенно пошел с persist persist(), если, как вы сказали:

(...) Я точно знаю, что я всегда создаю новый экземпляр объектов для сохранения (...)

Вот в чем заключается этот метод - он защитит вас в тех случаях, когда сущность уже существует (и откатит вашу транзакцию).

2 голосов
/ 16 января 2018

Если вы используете назначенный генератор, с использованием merge вместо persist может вызвать избыточный оператор SQL , что повлияет на производительность.

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

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

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

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

Сначала мы должны определить все состояния сущности:

  • New (Transient)

    Вновь созданный объект, который никогда не был связан с Hibernate Session (он же Persistence Context) и не сопоставлен ни с одной строкой таблицы базы данных, считается находящимся в состоянии New (Transient).

    Чтобы стать постоянным, нам нужно либо явно вызвать метод EntityManager#persist, либо использовать транзитивный механизм персистентности.

  • Постоянный (управляемый)

    Постоянный объект был связан со строкой таблицы базы данных, и он управляется текущим текущим контекстом постоянства.Любое изменение, внесенное в такой объект, будет обнаружено и распространено в базу данных (во время сброса сеанса).С Hibernate нам больше не нужно выполнять операторы INSERT / UPDATE / DELETE.Hibernate использует рабочий стиль с транзакционной записью , и изменения синхронизируются в самый последний ответственный момент, во время текущего Session времени сброса.

  • Detached

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

    Чтобы связать отдельную сущность с активным сеансом Hibernate, вы можете выбрать один из следующих параметров:

    • Повторное подключение

      Hibernate (но не JPA 2.1) поддерживает повторное подключение через метод обновления Session #.Сеанс Hibernate может связать только один объект Entity для данной строки базы данных.Это связано с тем, что постоянный контекст действует как кэш в памяти (кэш первого уровня) и только одно значение (сущность) связано с данным ключом (тип сущности и идентификатор базы данных).Сущность может быть повторно присоединена, только если нет другого объекта JVM (соответствующего той же строке базы данных), уже связанного с текущим сеансом Hibernate.

    • Объединение

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

  • Удалено

    Хотя JPA требует, чтобы разрешалось удалять только управляемые объекты, Hibernate также можетудалить отдельные объекты (но только через вызов метода Session # delete).Удаленный объект запланирован только для удаления, и фактический оператор DELETE базы данных будет выполнен во время сброса сеанса.

Чтобы лучше понять переходы состояния JPA, вы можете визуализировать следующую диаграмму:

enter image description here

Или, если вы используете специальный API Hibernate:

enter image description here

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