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



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



методы, которые я определил до сих пор являются:




  • save()

  • update()

  • saveOrUpdate()

  • saveOrUpdateCopy()

  • merge()

  • persist()

757   8  

8 ответов:

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

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

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

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

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

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

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

╔══════════════╦═══════════════════════════════╦════════════════════════════════╗
║    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()         ║
║              ║                               ║                                ║
╚══════════════╩═══════════════════════════════╩════════════════════════════════╝
  • посмотреть Форум Гибернации для объяснения тонких различий между сохранением и сохранением. Похоже, разница заключается в том, когда оператор INSERT в конечном итоге выполняется. Так как сохранить возвращает идентификатор, оператор INSERT должен выполняться мгновенно независимо от состояния транзакции (что, как правило, плохо). остаются не будет выполнять никаких операторов за пределами текущего запущенного транзакция только для присвоения идентификатора. Сохранить / Сохранить обе работы на переходные экземпляры, т. е. экземпляры, которые еще не имеют назначенного идентификатора и как таковые не сохраняются в БД.

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

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

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

исключение NonUniqueObjectException, возникающее при использовании сеанса.saveOrUpdate () в Hibernate является одним из моих. Я буду добавлять новые функции в сложное приложение. Все мои модульные тесты работают нормально. Затем в тестирование пользовательского интерфейса, стараясь сохранить объект, я получаю исключение с сообщением "другой объект с тем же значение идентификатора уже был связан с сессии."Вот пример кода из Java Persistence с 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 сообщает нам о проблеме через исключение 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.поглощать.)(

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

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

на самом деле разница между hibernate save() и persist() методы зависят от класса генератора, который мы используем.

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

long s = session.save(k);

в этом же случае, persist() будет никогда не возвращайте клиенту никакой ценности.

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

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

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

save ()

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

persist ()

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

saveOrUpdate()

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

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

update ()

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

merge ()

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

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

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

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

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

Comments

    Ничего не найдено.