在OSIV Web环境中使用JPA / Hibernate让我很生气;)
以下场景:我有一个通过JPA加载的实体A,并且有一个B实体的集合。那些B实体有一个必填字段。
当用户通过按webapp中的链接向A添加新B时,未设置该必填字段(因为没有合理的默认值)。
在下一个http请求时,OSIV过滤器尝试合并A实体,但由于Hibernate抱怨新B没有设置必填字段,因此失败。
javax.persistence.PersistenceException: org.hibernate.PropertyValueException: not-null property references a null or transient value
阅读JPA规范,我认为没有迹象表明在合并阶段需要这些检查(我没有活动交易)
当用户按下“保存”(又名entitymanager.persist())作为保存按钮不知道B的地方时,我无法将B的集合保留在A之外并仅将它们添加到A. ,只有A。
A和B也只是例子,我到处都有类似的东西..
有什么想法吗?其他JPA实现在这里的行为是否相同?
提前致谢。
答案 0 :(得分:2)
我做了很多阅读和测试。问题来自于我对JPA / Hibernate的误解。 merge()总是对数据库进行命中,并为实体安排更新。我在JPA规范中没有发现任何提及,但是“Java Persistence with Hibernate”一书确实提到过它。
通过EntityManager(以及Session作为回退)API,它看起来好像没有办法将实体分配给当前持久化上下文而不安排更新。毕竟,我想要的是导航对象图,根据需要更改属性并在以后触发更新(如果需要,可以进行版本检查)。我认为使用ORM的每个Webapp都必须做什么?
我正在寻找的基本工作流程:
使用来自spring的OSIV过滤器和wicket的IModel实现,我认为我已经存档了这个。
我基本上看到了两种可能的方式:
a)加载实体和进入某个页面时所需的所有关联(用例),让它们分离,在几个http请求过程中根据需要添加/更改它们。当用户启动保存时,重新附加它们(验证器将确保有效状态)并将它们提交给数据库。
b)使用当前设置,但要确保所有新添加的实体都设置了所有必需的字段(可能使用了一些向导组件)。对于每个merge(),我仍然会对数据库进行所有更新,但希望数据库管理员不会意识到;)
其他人如何在网络环境中使用JPA?还有其他选择吗?