Hibernate有一些方法,它们以某种方式获取对象并将其放入数据库中。它们之间的区别是什么,什么时候使用哪个,为什么没有一种智能方法知道什么时候使用什么?

到目前为止,我已经确定的方法是:

save () (更新) saveOrUpdate () saveOrUpdateCopy () 合并() persist ()


当前回答

以下答案没有一个是正确的。 所有这些方法看似相似,但实际上做的事情完全不同。 很难给出简短的评论。最好提供关于这些方法的完整文档链接: http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/objectstate.html

其他回答

╔══════════════╦═══════════════════════════════╦════════════════════════════════╗
║    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()         ║
║              ║                               ║                                ║
╚══════════════╩═══════════════════════════════╩════════════════════════════════╝

这个链接很好地解释了:

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

我们都有一些偶尔遇到的问题,当我们再次看到它们时,我们知道我们已经解决了这个问题,但不记得是如何解决的。

在Hibernate中使用Session.saveOrUpdate()时抛出的NonUniqueObjectException就是我的一个。我将为一个复杂的应用程序添加新功能。我所有的单元测试都运行正常。然后在测试UI时,试图保存一个对象,我开始得到一个异常,消息是“具有相同标识符值的不同对象已经与会话关联”。下面是一些来自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 Session时,我们正在使用的持久对象被分离。这意味着数据仍然在应用程序的内存中,但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返回对实例最新更新版本的引用。它不是将项重新附加到Session。如果您测试实例是否相等(item == item3),您将发现在这种情况下它返回false。从现在开始,您可能希望使用item3。

还需要注意的是,Java Persistence API (JPA)没有分离和重新连接对象的概念,而是使用EntityManager.persist()和EntityManager.merge()。

我发现在使用Hibernate时,saveOrUpdate()通常足以满足我的需要。通常只有当我的对象可以引用相同类型的对象时,我才需要使用merge。最近,异常的原因是在验证引用不是递归的代码中。作为验证的一部分,我将相同的对象加载到会话中,导致了错误。

您在哪里遇到过这个问题?合并对你有用吗?还是你需要另一种解决方案?你喜欢总是使用归并,还是喜欢只在特定情况下使用它

以下答案没有一个是正确的。 所有这些方法看似相似,但实际上做的事情完全不同。 很难给出简短的评论。最好提供关于这些方法的完整文档链接: http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/objectstate.html

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

If our generator class is assigned, then there is no difference between save() and persist() methods. Because generator ‘assigned’ means, as a programmer we need to give the primary key value to save in the database right [ Hope you know this generators concept ] In case of other than assigned generator class, suppose if our generator class name is Increment means hibernate it self will assign the primary key id value into the database right [ other than assigned generator, hibernate only used to take care the primary key id value remember ], so in this case if we call save() or persist() method then it will insert the record into the database normally But hear thing is, save() method can return that primary key id value which is generated by hibernate and we can see it by

long s = session.save(k);

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

请注意,如果对已分离对象调用更新,无论是否更改对象,数据库中总是会完成更新。如果不是你想要的,你应该使用Session.lock()和LockMode.None。

只有当对象在当前会话范围之外被更改时(当处于分离模式时),才应该调用update。