我正在尝试了解的语义Session.persist(),以及实体管理器对未保存的瞬态实例的确切含义。我要实现的只是向会话添加一个新的临时实例,并INSERT在刷新会话时让Hibernate执行一个。
Session.persist()
INSERT
我发现如果持久保存一个新实例,然后在同一会话中对其进行修改,则实体管理器将同时生成INSERT和UPDATE语句,这可能会导致约束冲突。
UPDATE
例如,假设我有一个带有列 栏 和以下服务方法的实体关系 Foo 。NOT NULL __
NOT NULL
@Transactional void persistFoo(String bar) { Foo foo = new Foo(); session.persist(foo); foo.setBar(bar); }
尽管我们为提供了一个值bar,但是执行此代码将违反数据库中的 NULL 约束。
bar
BatchUpdateException: Cannot insert the value NULL into column 'bar'
在Hibernate文档指出以下。
persist()使瞬态实例持久化。但是,它不能保证将标识符值立即分配给持久实例,分配可能会在刷新时发生。
在INSERT该届会议在事务块结束时刷新点确实执行,但它仍然是从对象属性值参数化 ,因为它是 何时persist()被调用。
persist()
我知道可以通过一些简单的更改来解决此示例说明的特定问题,但是我对尝试理解其 应 如何工作更感兴趣。
我的问题是,这种行为只是合同的一部分,Session.persist()还是可以更改?如果是这样,我如何告诉会话将生成的INSERT语句的收集参数推迟到实际执行该语句之前?
是的,这是的合同的一部分Session.persist()。根据Hibernate文档,这是执行SQL的顺序:
按执行顺序插入 更新 删除收集元素 插入收集元素 按执行顺序删除
该顺序是官方Hibernate API的一部分,应用程序在操纵其实体图时会依赖它。
Session.persist()立即在INSERT语句后进行更改会破坏该合同,并在某些用例中引起问题。
假设我们有一个User实体,并且两个用户可能以某种方式彼此关联。然后,我们可以将两者插入一个事务中:
User
persist(user1); persist(user2); user1.setPartner(user2); user2.setPartner(user1);
如果所有内容都存储在INSERT语句中,则在持久化时会违反外键约束user1。
user1
通常,通过确保仅传递给的状态以persist结束INSERT,Hibernate为我们提供了更大的灵活性来满足基础数据库的约束。
persist
我不知道可以更改此行为的任何配置。当然,正如您提到的,persist只要不违反数据库约束,就可以重组代码,以便在设置所有值之后调用该代码。