Java Hibernate中的不同保存方法有什么区别?

Java Hibernate中的不同保存方法有什么区别?,java,hibernate,persistence,Java,Hibernate,Persistence,Hibernate有几种方法,它们以某种方式将对象放入数据库。它们之间的区别是什么,何时使用,为什么没有一种智能方法知道何时使用什么 到目前为止,我确定的方法有: save() update() saveOrUpdate() saveOrUpdateCopy() merge() persist() 以下是我对这些方法的理解。这些主要是基于想法,因为我在实践中没有使用所有这些 保存或更新 根据某些检查调用save或update。例如,如果不存在标识符,则调用save。否则将调用update 保存

Hibernate有几种方法,它们以某种方式将对象放入数据库。它们之间的区别是什么,何时使用,为什么没有一种智能方法知道何时使用什么

到目前为止,我确定的方法有:

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

    • 以下是我对这些方法的理解。这些主要是基于想法,因为我在实践中没有使用所有这些

      保存或更新 根据某些检查调用save或update。例如,如果不存在标识符,则调用save。否则将调用update

      保存 保存一个实体。如果不存在标识符,则将分配标识符。如果有人这样做了,它实际上是在进行更新。返回实体的生成ID

      更新 尝试使用现有标识符持久化实体。如果不存在标识符,我相信会引发异常

      saveOrUpdateCopy 这已弃用,不应再使用。相反,有

      合并 这就是我的知识开始动摇的地方。这里重要的是瞬态、分离和持久实体之间的区别。有关对象状态的详细信息。使用save&update,您可以处理持久对象。它们链接到会话,以便Hibernate知道发生了什么变化。但是,当您有一个瞬态对象时,不涉及会话。在这些情况下,您需要使用“合并”进行更新,并使用“持久化”进行保存

      持续 如上所述,这用于瞬态对象。它不会返回生成的ID。

      • 有关持久化和保存之间细微差异的解释,请参见。看起来区别在于INSERT语句最终执行的时间。由于save确实返回标识符,因此无论事务的状态如何(这通常是一件坏事),都必须立即执行INSERT语句Persist不会在当前运行的事务之外执行任何语句,只是为了分配标识符。 保存/持久化这两种方法都适用于瞬态实例,即尚未分配标识符的实例,因此不会保存在数据库中

      • 更新合并都适用于分离的实例,即数据库中有相应条目但当前未连接到会话(或由会话管理)的实例。它们之间的区别在于传递给函数的实例发生了什么update尝试重新附加实例,这意味着现在必须没有其他持久实体实例附加到会话,否则会引发异常合并,但是,只需将所有值复制到会话中的持久实例(如果当前未加载,则将加载该实例)。输入对象未更改。因此,合并更新更通用,但可能会使用更多资源


      请注意,如果对分离的对象调用更新,则无论是否更改了对象,数据库中始终会有更新。如果它不是您想要的,您应该将Session.lock()与LockMode.None一起使用


      仅当对象在当前会话范围之外更改时(在分离模式下),才应调用update。

      实际上,hibernate
      save()
      persist()
      方法之间的区别取决于我们使用的生成器类

      如果指定了生成器类,则
      save()
      persist(
      )方法之间没有区别。因为生成器“已分配”意味着,作为程序员,我们需要给出主键值以正确保存在数据库中[希望您了解生成器的概念] 在非指定的生成器类的情况下,假设我们的生成器类名为Increment意味着hibernate,它将自己将主键id值分配到数据库右侧[除了指定的生成器,hibernate仅用于处理主键id值,记住],因此在这种情况下,如果我们调用
      save()
      persist()
      方法,然后它将正常地将记录插入数据库 但听说,
      save()
      方法可以返回由hibernate生成的主键id值,我们可以通过

      long s = session.save(k);
      

      在同样的情况下,
      persist()
      将永远不会向客户端返回任何值。

      以下答案都不正确。 所有这些方法看起来都很相似,但实际上却完全不同。 很难给出简短的评论。最好提供有关这些方法的完整文档的链接:

      此链接以良好的方式解释:

      我们都会遇到那些我们很少遇到的问题,当我们再次看到它们时,我们知道我们已经解决了这个问题,但不记得是怎么解决的

      在Hibernate中使用Session.saveOrUpdate()时引发的UnuniqueObjectException是我的一个问题。我将向一个复杂的应用程序添加新功能。我的所有单元测试都可以正常工作。然后在测试UI、尝试保存对象时,我开始收到一个异常消息“具有相同标识符值的另一个对象已与会话关联。”下面是使用Hibernate的Java持久化的一些示例代码

                  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会话时,persi
              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();
      
      ╔══════════════╦═══════════════════════════════╦════════════════════════════════╗
      ║    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()         ║
      ║              ║                               ║                                ║
      ╚══════════════╩═══════════════════════════════╩════════════════════════════════╝
      
      Session ses1 = sessionFactory.openSession();
      
          Transaction tx1 = ses1.beginTransaction();
      
          HibEntity entity = getHibEntity();
      
          ses1.persist(entity);
          ses1.evict(entity);
      
          ses1.merge(entity);
      
          ses1.delete(entity);
      
          tx1.commit();
      
      Session ses1 = sessionFactory.openSession();
      
          Transaction tx1 = ses1.beginTransaction();
          HibEntity entity = getHibEntity();
      
          ses1.persist(entity);
          ses1.evict(entity);
      
          HibEntity copied = (HibEntity)ses1.merge(entity);
          ses1.delete(copied);
      
          tx1.commit();
      
      Session ses1 = sessionFactory.openSession();
      
          Transaction tx1 = ses1.beginTransaction();
      
          HibEntity entity = getHibEntity();
      
          ses1.persist(entity);
          ses1.evict(entity);
      
          ses1.update(entity);
      
          ses1.delete(entity);
      
          tx1.commit();
      
      doInJPA(entityManager -> {
          Book book = new Book()
          .setIsbn("978-9730228236")
          .setTitle("High-Performance Java Persistence")
          .setAuthor("Vlad Mihalcea");
      
          entityManager.persist(book);
          
          LOGGER.info(
              "Persisting the Book entity with the id: {}", 
              book.getId()
          );
      });
      
      CALL NEXT VALUE FOR hibernate_sequence
      
      -- Persisting the Book entity with the id: 1
      
      INSERT INTO book (
          author, 
          isbn, 
          title, 
          id
      ) 
      VALUES (
          'Vlad Mihalcea', 
          '978-9730228236', 
          'High-Performance Java Persistence', 
          1
      )
      
      doInJPA(entityManager -> {
          Book book = new Book()
          .setIsbn("978-9730228236")
          .setTitle("High-Performance Java Persistence")
          .setAuthor("Vlad Mihalcea");
      
          Session session = entityManager.unwrap(Session.class);
      
          Long id = (Long) session.save(book);
      
          LOGGER.info(
              "Saving the Book entity with the id: {}", 
              id
          );
      });
      
      CALL NEXT VALUE FOR hibernate_sequence
      
      -- Saving the Book entity with the id: 1
      
      INSERT INTO book (
          author, 
          isbn, 
          title, 
          id
      ) 
      VALUES (
          'Vlad Mihalcea', 
          '978-9730228236', 
          'High-Performance Java Persistence', 
          1
      )
      
      Book _book = doInJPA(entityManager -> {
          Book book = new Book()
          .setIsbn("978-9730228236")
          .setTitle("High-Performance Java Persistence")
          .setAuthor("Vlad Mihalcea");
      
          entityManager.persist(book);
      
          return book;
      });
      
      LOGGER.info("Modifying the Book entity");
      
      _book.setTitle(
          "High-Performance Java Persistence, 2nd edition"
      );
      
      doInJPA(entityManager -> {
          Session session = entityManager.unwrap(Session.class);
      
          session.update(_book);
      
          LOGGER.info("Updating the Book entity");
      });
      
      CALL NEXT VALUE FOR hibernate_sequence
      
      INSERT INTO book (
          author, 
          isbn, 
          title, 
          id
      ) 
      VALUES (
          'Vlad Mihalcea', 
          '978-9730228236', 
          'High-Performance Java Persistence', 
          1
      )
      
      -- Modifying the Book entity
      -- Updating the Book entity
      
      UPDATE 
          book 
      SET 
          author = 'Vlad Mihalcea', 
          isbn = '978-9730228236', 
          title = 'High-Performance Java Persistence, 2nd edition'
      WHERE 
          id = 1
      
      @Entity(name = "Book")
      @Table(name = "book")
      @SelectBeforeUpdate
      public class Book {
      
          //Code omitted for brevity
      }
      
      Book _book = doInJPA(entityManager -> {
          Book book = new Book()
          .setIsbn("978-9730228236")
          .setTitle("High-Performance Java Persistence")
          .setAuthor("Vlad Mihalcea");
      
          entityManager.persist(book);
      
          return book;
      });
      
      doInJPA(entityManager -> {
          Session session = entityManager.unwrap(Session.class);
      
          session.update(_book);
      });
      
      INSERT INTO book (
          author, 
          isbn, 
          title, 
          id
      ) 
      VALUES (
          'Vlad Mihalcea', 
          '978-9730228236', 
          'High-Performance Java Persistence', 
          1
      )
      
      SELECT 
          b.id,
          b.author AS author2_0_,
          b.isbn AS isbn3_0_,
          b.title AS title4_0_
      FROM 
          book b
      WHERE 
          b.id = 1
      
      Book _book = doInJPA(entityManager -> {
          Book book = new Book()
          .setIsbn("978-9730228236")
          .setTitle("High-Performance Java Persistence")
          .setAuthor("Vlad Mihalcea");
      
          Session session = entityManager.unwrap(Session.class);
          session.saveOrUpdate(book);
      
          return book;
      });
      
      _book.setTitle("High-Performance Java Persistence, 2nd edition");
      
      doInJPA(entityManager -> {
          Session session = entityManager.unwrap(Session.class);
          session.saveOrUpdate(_book);
      });
      
      Book _book = doInJPA(entityManager -> {
          Book book = new Book()
          .setIsbn("978-9730228236")
          .setTitle("High-Performance Java Persistence")
          .setAuthor("Vlad Mihalcea");
      
          Session session = entityManager.unwrap(Session.class);
          session.saveOrUpdate(book);
      
          return book;
      });
      
      _book.setTitle(
          "High-Performance Java Persistence, 2nd edition"
      );
      
      try {
          doInJPA(entityManager -> {
              Book book = entityManager.find(
                  Book.class, 
                  _book.getId()
              );
      
              Session session = entityManager.unwrap(Session.class);
              session.saveOrUpdate(_book);
          });
      } catch (NonUniqueObjectException e) {
          LOGGER.error(
              "The Persistence Context cannot hold " +
              "two representations of the same entity", 
              e
          );
      }
      
      org.hibernate.NonUniqueObjectException: 
          A different object with the same identifier value was already associated with the session : [com.vladmihalcea.book.hpjp.hibernate.pc.Book#1]
          at org.hibernate.engine.internal.StatefulPersistenceContext.checkUniqueness(StatefulPersistenceContext.java:651)
          at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.performUpdate(DefaultSaveOrUpdateEventListener.java:284)
          at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsDetached(DefaultSaveOrUpdateEventListener.java:227)
          at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:92)
          at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:73)
          at org.hibernate.internal.SessionImpl.fireSaveOrUpdate(SessionImpl.java:682)
          at org.hibernate.internal.SessionImpl.saveOrUpdate(SessionImpl.java:674)
      
      Book _book = doInJPA(entityManager -> {
          Book book = new Book()
          .setIsbn("978-9730228236")
          .setTitle("High-Performance Java Persistence")
          .setAuthor("Vlad Mihalcea");
      
          entityManager.persist(book);
      
          return book;
      });
      
      LOGGER.info("Modifying the Book entity");
      
      _book.setTitle(
          "High-Performance Java Persistence, 2nd edition"
      );
      
      doInJPA(entityManager -> {
          Book book = entityManager.merge(_book);
      
          LOGGER.info("Merging the Book entity");
      
          assertFalse(book == _book);
      });
      
      INSERT INTO book (
          author, 
          isbn, 
          title, 
          id
      ) 
      VALUES (
          'Vlad Mihalcea', 
          '978-9730228236', 
          'High-Performance Java Persistence', 
          1
      )
      
      -- Modifying the Book entity
      
      SELECT 
          b.id,
          b.author AS author2_0_,
          b.isbn AS isbn3_0_,
          b.title AS title4_0_
      FROM 
          book b
      WHERE 
          b.id = 1
      
      -- Merging the Book entity
      
      UPDATE 
          book 
      SET 
          author = 'Vlad Mihalcea', 
          isbn = '978-9730228236', 
          title = 'High-Performance Java Persistence, 2nd edition'
      WHERE 
          id = 1