Java Hibernate中的不同保存方法有什么区别?
Hibernate有几种方法,它们以某种方式将对象放入数据库。它们之间的区别是什么,何时使用,为什么没有一种智能方法知道何时使用什么 到目前为止,我确定的方法有:Java Hibernate中的不同保存方法有什么区别?,java,hibernate,persistence,Java,Hibernate,Persistence,Hibernate有几种方法,它们以某种方式将对象放入数据库。它们之间的区别是什么,何时使用,为什么没有一种智能方法知道何时使用什么 到目前为止,我确定的方法有: save() update() saveOrUpdate() saveOrUpdateCopy() merge() persist() 以下是我对这些方法的理解。这些主要是基于想法,因为我在实践中没有使用所有这些 保存或更新 根据某些检查调用save或update。例如,如果不存在标识符,则调用save。否则将调用update 保存
save()
update()
saveOrUpdate()
saveOrUpdateCopy()
merge()
persist()
- 有关持久化和保存之间细微差异的解释,请参见。看起来区别在于INSERT语句最终执行的时间。由于save确实返回标识符,因此无论事务的状态如何(这通常是一件坏事),都必须立即执行INSERT语句Persist不会在当前运行的事务之外执行任何语句,只是为了分配标识符。 保存/持久化这两种方法都适用于瞬态实例,即尚未分配标识符的实例,因此不会保存在数据库中
- 更新和合并都适用于分离的实例,即数据库中有相应条目但当前未连接到会话(或由会话管理)的实例。它们之间的区别在于传递给函数的实例发生了什么update尝试重新附加实例,这意味着现在必须没有其他持久实体实例附加到会话,否则会引发异常合并,但是,只需将所有值复制到会话中的持久实例(如果当前未加载,则将加载该实例)。输入对象未更改。因此,合并比更新更通用,但可能会使用更多资源
- 以下是我对这些方法的理解。这些主要是基于想法,因为我在实践中没有使用所有这些
保存或更新
根据某些检查调用save或update。例如,如果不存在标识符,则调用save。否则将调用update
保存
保存一个实体。如果不存在标识符,则将分配标识符。如果有人这样做了,它实际上是在进行更新。返回实体的生成ID
更新
尝试使用现有标识符持久化实体。如果不存在标识符,我相信会引发异常
saveOrUpdateCopy
这已弃用,不应再使用。相反,有
合并
这就是我的知识开始动摇的地方。这里重要的是瞬态、分离和持久实体之间的区别。有关对象状态的详细信息。使用save&update,您可以处理持久对象。它们链接到会话,以便Hibernate知道发生了什么变化。但是,当您有一个瞬态对象时,不涉及会话。在这些情况下,您需要使用“合并”进行更新,并使用“持久化”进行保存
持续
如上所述,这用于瞬态对象。它不会返回生成的ID。
仅当对象在当前会话范围之外更改时(在分离模式下),才应调用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