在JPA/Hibernate中合并/重新附加实体而不更新数据库

4
在OSIV Web环境中使用JPA/Hibernate让我感到很疯狂 ;)
以下是场景:我有一个通过JPA加载的实体A,它有一组B实体。这些B实体有一个必填字段。
当用户通过Web应用程序中的链接向A添加新的B时,该必填字段未设置(因为没有合理的默认值)。
在下一个http请求时,OSIV过滤器尝试合并A实体,但由于Hibernate抱怨新的B未设置必填字段,因此失败了。
javax.persistence.PersistenceException: org.hibernate.PropertyValueException: not-null property references a null or transient value

阅读JPA规范,我没有看到这些检查在合并阶段是必需的(我没有活动事务)。我不能将B的集合保留在A之外,只有当用户按下“保存”(即entitymanager.persist())时将它们添加到A中,因为保存按钮所在的位置不知道B,只知道A。此外,A和B只是示例,我在许多地方都有类似的东西... 有什么想法吗?其他JPA实现在这里表现相同吗?提前感谢。
1个回答

2
我进行了大量阅读和测试,问题出在我对JPA/Hibernate的误解上。merge()总是会在数据库中查询并为实体安排一个更新。我没有在JPA规范中找到这方面的任何提及,但《Java Persistence with Hibernate》一书确实提到了这点。
浏览EntityManager(并作为后备的Session)API,似乎没有办法只将实体分配给当前持久化上下文而不安排更新。毕竟,我想要的是导航对象图,根据需要更改属性,并稍后触发更新(如果需要进行版本检查)。我认为每个使用ORM的Web应用程序都必须这样做?
我正在寻找的基本工作流程:
1.从数据库加载实体(或创建新实体) 2.使实体(及其所有关联)变为游离状态(因为EntitManager在HTTP请求结束时关闭) 3.当下一个HTTP请求到达时,再次使用这些对象,导航树而不担心LazyInitExceptions 4.调用方法以持久化完成1-3期间所做的所有更改
通过Spring中的OSIV过滤器和Wicket中的IModel实现,我认为已经实现了这一点。
我基本上看到两种可能的解决方法:
a)在进入特定页面(用例)时加载实体和所有所需的关联,让它们成为游离状态,在多个HTTP请求的过程中根据需要添加/更改它们。然后,在用户启动保存操作时重新附加它们(验证器将确保有效状态)并将它们提交到数据库。
b)使用当前设置,但确保所有新添加的实体都设置了所需的所有字段(可能使用某些向导组件)。我仍然会对每个merge()进行所有更新,但希望数据库管理员不会意识到这一点 ;)
其他人在Web环境中如何使用JPA?还有其他选项吗?

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接