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

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

  • save()
  • update()
  • saveOrUpdate()
  • saveOrUpdateCopy()
  • merge()
  • persist()
有帮助吗?

解决方案

以下是我对这些方法的理解。主要是这些基于 应用程序编程接口 尽管我在实践中并没有使用所有这些。

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

节省持久化一个实体。如果标识符不存在,将分配一个标识符。如果这样做,它本质上是在进行更新。返回生成的实体 ID。

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

保存或更新复制这已被弃用,不应再使用。相反有...

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

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

其他提示

╔══════════════╦═══════════════════════════════╦════════════════════════════════╗
║    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/

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

在 Hibernate 中使用 Session.saveOrUpdate() 时抛出的 NonUniqueObjectException 是我的问题之一。我将为复杂的应用程序添加新功能。我所有的单元测试都工作正常。然后,在测试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 会话时,我们正在使用的持久对象将被分离。这意味着数据仍在应用程序的内存中,但 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();

需要注意的是,合并返回对实例新更新版本的引用。它不会将项目重新附加到会话。如果您测试实例相等性(item == item3),您会发现在这种情况下它返回 false。从现在开始,您可能希望使用 item3。

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

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

你在哪里遇到过这个问题?合并对您有用还是您需要其他解决方案?您更喜欢始终使用合并,还是更喜欢仅在特定情况下需要时使用它

其实hibernate的区别 save()persist() 方法取决于我们正在使用的生成器类。

如果我们的生成器类被分配,那么之间没有区别 save()persist() 方法。因为发电机“分配”是指作为程序员,我们需要给出主要的键值以保存在数据库中的权利[希望您知道该生成器概念外],但如果分配了生成器类,则假设如果我们的生成器类名称为增量Hibernate IT自我会将主密钥ID值分配到数据库中[除了分配的发电机外,Hibernate仅用于照顾主要密钥ID值的记住],因此,在这种情况下, save() 或者 persist() 方法,然后它会将记录正常插入数据库 但听说是, save() 方法可以返回由 hibernate 生成的主键 id 值,我们可以通过以下方式查看它

long s = session.save(k);

在同样的情况下, persist() 永远不会给客户任何价值。

我找到了一个很好的例子,显示了所有休眠保存方法之间的差异:

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

简而言之,根据上面的链接:

节省()

  • 我们可以在事务之外调用此方法。如果我们在没有事务的情况下使用它,并且实体之间有级联,那么除非我们刷新会话,否则只有主要实体会被保存。
  • 因此,如果还有从主对象映射的其他对象,它们会在提交事务时或刷新会话时保存。

坚持()

  • 它类似于在事务中使用 save(),因此它是安全的并且可以处理任何级联对象。

保存或更新()

  • 可以在有或没有事务的情况下使用,就像 save() 一样,如果在没有事务的情况下使用,映射的实体将不会被保存,除非我们刷新会话。

  • 根据提供的数据插入或更新查询结果。如果数据库中存在数据,则执行更新查询。

更新()

  • 当我们知道我们只更新实体信息时,应该使用 Hibernate 更新。此操作将实体对象添加到持久上下文中,并在提交事务时跟踪并保存进一步的更改。
  • 因此,即使在调用更新之后,如果我们在实体中设置任何值,它们也会在事务提交时更新。

合并()

  • Hibernate 合并可用于更新现有值,但是此方法从传递的实体对象创建一个副本并返回它。返回的对象是持久上下文的一部分,并跟踪任何更改,不跟踪传递的对象。这是 merge() 与所有其他方法的主要区别。

另外,对于所有这些的实际示例,请参阅我上面提到的链接,它显示了所有这些不同方法的示例。

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

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

正如我所解释的 本文, ,大多数时候您应该更喜欢 JPA 方法,并且 update 用于批处理任务。

JPA 或 Hibernate 实体可以处于以下四种状态之一:

  • 瞬态(新)
  • 托管(持久)
  • 独立的
  • 已删除(已删除)

从一种状态到另一种状态的转换是通过 EntityManager 或 Session 方法完成的。

例如,JPA EntityManager 提供以下实体状态转换方法。

enter image description here

冬眠 Session 实现所有 JPA EntityManager 方法并提供了一些额外的实体状态转换方法,例如 save, saveOrUpdateupdate.

enter image description here

坚持

要将实体的状态从瞬态(新)更改为托管(持久),我们可以使用 persist JPA提供的方法 EntityManager Hibernate 也继承了这一点 Session.

persist 方法触发一个 PersistEvent 这是由 DefaultPersistEventListener Hibernate 事件监听器。

因此,在执行以下测试用例时:

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()
    );
});

Hibernate 生成以下 SQL 语句:

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
)

请注意, id 在附加之前分配 Book 实体到当前持久性上下文。这是必需的,因为托管实体存储在 Map 结构体,其中键由实体类型及其标识符构成,值是实体引用。这就是JPA的原因 EntityManager 和冬眠 Session 被称为一级缓存。

打电话时 persist, ,该实体仅附加到当前正在运行的持久性上下文,并且 INSERT 可以推迟到 flush 叫做。

唯一的例外是 身份生成器 它会立即触发 INSERT,因为这是获取实体标识符的唯一方法。因此,Hibernate 无法使用 IDENTITY 生成器批量插入实体。有关此主题的更多详细信息,请查看 本文.

节省

Hibernate 特定的 save 方法早于 JPA,并且自 Hibernate 项目开始就可用。

save 方法触发一个 SaveOrUpdateEvent 这是由 DefaultSaveOrUpdateEventListener Hibernate 事件监听器。因此, save 方法相当于 updatesaveOrUpdate 方法。

看看如何 save 方法有效,请考虑以下测试用例:

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
    );
});

运行上面的测试用例时,Hibernate 生成以下 SQL 语句:

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
)

如您所见,结果与 persist 方法调用。然而,与 persist, , 这 save 方法返回实体标识符。

欲了解更多详情,请查看 本文.

更新

Hibernate 特定的 update 方法的目的是绕过 脏检查机制 并在刷新时强制更新实体。

update 方法触发一个 SaveOrUpdateEvent 这是由 DefaultSaveOrUpdateEventListener Hibernate 事件监听器。因此, update 方法相当于 savesaveOrUpdate 方法。

看看如何 update 方法的工作原理考虑以下示例,该示例持续存在 Book 一个事务中的实体,然后在该实体处于分离状态时对其进行修改,并使用以下命令强制执行 SQL UPDATE: update 方法调用。

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");
});

当执行上面的测试用例时,Hibernate 生成以下 SQL 语句:

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

请注意, UPDATE 在持久性上下文刷新期间执行,就在提交之前,这就是为什么 Updating the Book entity 首先记录消息。

使用 @SelectBeforeUpdate 以避免不必要的更新

现在,即使实体在分离状态下没有更改,更新也始终会被执行。为了防止这种情况,您可以使用 @SelectBeforeUpdate Hibernate注释将触发 SELECT 获取的语句 loaded state 然后由脏检查机制使用。

所以,如果我们注释 Book 实体与 @SelectBeforeUpdate 注解:

@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);
});

Hibernate执行以下SQL语句:

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

请注意,这一次,没有 UPDATE 自 Hibernate 脏检查机制检测到实体未被修改后执行。

保存或更新

Hibernate 特定的 saveOrUpdate 方法只是一个别名 saveupdate.

saveOrUpdate 方法触发一个 SaveOrUpdateEvent 这是由 DefaultSaveOrUpdateEventListener Hibernate 事件监听器。因此, update 方法相当于 savesaveOrUpdate 方法。

现在,您可以使用 saveOrUpdate 当你想要持久化一个实体或强制一个 UPDATE 如下例所示。

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);
});

当心 NonUniqueObjectException

可能出现的一个问题是 save, update, , 和 saveOrUpdate 如果持久性上下文已包含具有相同 id 和相同类型的实体引用,如下例所示:

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
    );
}

现在,当执行上面的测试用例时,Hibernate 将抛出一个 NonUniqueObjectException 因为第二个 EntityManager 已经包含一个 Book 与我们传递给的实体具有相同标识符的实体 update, ,并且持久化上下文不能保存同一实体的两个表示。

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)

合并

为了避免 NonUniqueObjectException, ,你需要使用 merge JPA提供的方法 EntityManager 并由 Hibernate 继承 Session 以及。

正如中所解释的 本文, , 这 merge 如果在持久性上下文中没有找到实体引用,则从数据库中获取新的实体快照,并将分离实体的状态复制到传递给 merge 方法。

merge 方法触发一个 MergeEvent 这是由 DefaultMergeEventListener Hibernate 事件监听器。

看看如何 merge 方法的工作原理考虑以下示例,该示例持续存在 Book 一个事务中的实体,然后在该实体处于分离状态时对其进行修改,并将分离实体传递给 merge 在子序列持久性上下文中。

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);
});

运行上面的测试用例时,Hibernate执行了以下SQL语句:

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

请注意,返回的实体引用 merge 与我们传递给的分离的不同 merge 方法。

现在,尽管您应该更喜欢使用 JPA merge 复制分离实体状态时,额外的 SELECT 执行批处理任务时可能会出现问题。

因此,您应该更喜欢使用 update 当您确定没有实体引用已附加到当前运行的持久性上下文并且分离的实体已被修改时。

有关此主题的更多详细信息,请查看 本文.

结论

要持久化实体,您应该使用 JPA persist 方法。要复制分离的实体状态, merge 应该是首选。这 update 方法仅对批处理任务有用。这 savesaveOrUpdate 只是别名 update 你可能根本不应该使用它们。

一些开发商称 save 即使实体已经被管理,但这是一个错误并会触发冗余事件,因为对于托管实体,更新是在持久性上下文刷新时自动处理的。

欲了解更多详情,请查看 本文.

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

上面的答案都不完整。尽管 Leo Theobald 的答案看起来最接近。

基本点是 hibernate 如何处理实体的状态以及当状态发生变化时如何处理它们。一切都必须从同花顺和提交的角度来看待,而每个人似乎都完全忽略了这一点。

切勿使用 Hibernate 的保存方法。忘记它甚至存在于休眠状态!

坚持

正如每个人所解释的,持久基本上将实体从“瞬态”状态转换为“托管”状态。此时,slush 或 commit 可以创建一条插入语句。但该实体仍将保持“托管”状态。这不会随着冲洗而改变。

此时,如果你再次“坚持”,就不会发生任何变化。如果我们尝试持久化持久化实体,则不会再有任何保存。

当我们尝试驱逐该实体时,乐趣就开始了。

逐出是 Hibernate 的一个特殊功能,它将实体从“托管”转换为“分离”。我们不能对一个独立的实体调用持久化。如果我们这样做,那么 Hibernate 会引发异常,并且整个事务会在提交时回滚。

合并与更新

这是两个有趣的函数,以不同的方式处理时会做不同的事情。他们都试图将实体从“分离”状态转换为“托管”状态。但做法不同。

了解分离意味着某种“离线”状态的事实。托管表示“在线”状态。

观察下面的代码:

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();

同时在调试跟踪中我们可以看到Update没有像merge一样引发select的SQL查询。

删除

在上面的例子中我使用了delete,但没有谈论delete。删除基本上会将实体从托管状态转换为“已删除”状态。并且当刷新或提交时会发出删除命令来存储。

但是,可以使用 persist 方法将实体从“已删除”状态恢复到“托管”状态。

希望以上的解​​释能够解答大家的疑惑。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top