Hibernate中的persist()和merge()有什么区别?
Hibernate中的persist()和merge()有什么区别?
persist()
可以创build一个UPDATE&INSERT查询,例如:
SessionFactory sef = cfg.buildSessionFactory(); Session session = sef.openSession(); A a=new A(); session.persist(a); a.setName("Mario"); session.flush();
在这种情况下查询将会像这样产生:
Hibernate: insert into A (NAME, ID) values (?, ?) Hibernate: update A set NAME=? where ID=?
所以persist()
方法可以生成一个Insert和一个Update。
现在用merge()
:
SessionFactory sef = cfg.buildSessionFactory(); Session session = sef.openSession(); Singer singer = new Singer(); singer.setName("Luciano Pavarotti"); session.merge(singer); session.flush();
这是我在数据库中看到的:
SINGER_ID SINGER_NAME 1 Ricky Martin 2 Madonna 3 Elvis Presley 4 Luciano Pavarotti
现在使用merge()
更新logging
SessionFactory sef = cfg.buildSessionFactory(); Session session = sef.openSession(); Singer singer = new Singer(); singer.setId(2); singer.setName("Luciano Pavarotti"); session.merge(singer); session.flush();
这是我在数据库中看到的:
SINGER_ID SINGER_NAME 1 Ricky Martin 2 Luciano Pavarotti 3 Elvis Presley
JPA规范包含这些操作的语义的非常精确的描述,比在javadoc中更好:
应用于实体X的持久化操作的语义如下:
如果X是一个新的实体,它就变成了pipe理。 实体X将在事务提交之前或之前进入数据库,或作为刷新操作的结果。
如果X是一个先前存在的pipe理实体,则持久操作将忽略它。 但是,如果从X到这些其他实体的关系使用
cascade=PERSIST
或cascade=ALL
注释元素值进行注释,或者使用等效XML描述符元素进行了指定,则持久操作将级联到由X引用的实体。如果X是一个被删除的实体,它将被pipe理。
如果X是分离的对象,则在调用persist操作时可能会引发
EntityExistsException
或者在刷新或提交时抛出EntityExistsException
或其他PersistenceException
。对于由X的关系引用的所有实体Y,如果与Y的关系已用级联元素值
cascade=PERSIST
或cascade=ALL
进行注释,则将持久化操作应用于Y.
适用于实体X的合并操作的语义如下:
如果X是分离的实体,则将X的状态复制到具有相同标识的预先存在的被pipe理实体X'或创buildX的新被pipe理副本X'。
如果X是新的实体实例,则创build新的托pipe实体实例X',并将X的状态复制到新的托pipe实体实例X'中。
如果X是已删除的实体实例,则合并操作将抛出
IllegalArgumentException
exception(否则事务提交将失败)。如果X是托pipe实体,则合并操作会忽略它,但是,如果这些关系已使用级联元素值
cascade=MERGE
或cascade=ALL
注释进行注释,则合并操作将级联到由X关系引用的实体。对于由具有级联元素值
cascade=MERGE
或cascade=ALL
X的关系引用的所有实体Y,Y被recursion地合并为Y'。 对于由X引用的所有这样的Y,将X'设置为引用Y'。 (注意,如果X被pipe理,那么X与X'是同一个对象。)如果X是合并到X'的实体,并且引用了另一个实体Y,那么
cascade=MERGE
或cascade=ALL
没有被指定,那么从X'导航同一个关联产生一个被pipe理对象Y'的引用。与Y相同的持久性标识。
这是来自JPA。 以一种非常简单的方式:
persist(entity)应该与全新实体一起使用,将它们添加到数据库中(如果实体已经存在于数据库中,则会出现EntityExistsException throw)。
应该使用合并(实体),如果实体被分离并被改变,则将实体放回持久性上下文。
坚持只应该被称为新的实体,而合并则意味着重新分离的实体。
如果使用分配的生成器,则使用merge而不是persist可能会导致冗余的SQL语句 ,从而影响性能。
此外, 调用托pipe实体的合并也是一个错误,因为托pipe实体是由Hibernate自动pipe理的,并且在刷新持久性上下文时,它们的状态通过脏检查机制与数据库logging同步。
- 如何用entity framework通过id删除一个对象
- entity framework回滚并删除错误的迁移
- 在Python中将XML / HTML实体转换为Unicodestring
- 如何使用entity framework只更新一个字段?
- 如何禁用entity framework6.0中的迁移
- cascade = {“remove”} VS orphanRemoval = true VS ondelete =“CASCADE
- types或名称空间名称“对象”不存在于名称空间“System.Data”
- EF 4.1exception“提供程序没有返回ProviderManifestTokenstring”
- 为什么我们需要实体对象?