代码之家  ›  专栏  ›  技术社区  ›  bert

在jpa/hibernate中合并/重新附加而不更新db

  •  4
  • bert  · 技术社区  · 15 年前

    在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规范时,我没有看到在合并阶段需要这些检查的迹象(我没有活动的事务)

    我不能将B的集合保留在A之外,只能在用户按“save”(aka entitymanager.persist())时将它们添加到A中,因为save按钮所在的位置不知道B的情况,只知道A的情况。

    A和B也是唯一的例子,我在各地都有类似的东西。

    有什么想法吗?其他JPA实现在这里的行为是否相同?

    事先谢谢。

    1 回复  |  直到 15 年前
        1
  •  2
  •   bert    15 年前

    我做了很多阅读和测试。问题来自我对JPA/Hibernate的误解。merge()始终对数据库执行命中操作,并为实体安排更新。我没有在JPA规范中提到这一点,但是“Hibernate”的Java持久性确实提到了这一点。

    通过EntityManager(和会话作为回退)API,它看起来似乎无法在不安排更新的情况下将实体分配给当前持久上下文。毕竟,我想要的是导航对象图,根据需要更改属性,并在以后触发更新(如果需要,使用版本检查)。我认为每个使用ORM的webapp都必须做些什么?

    我正在寻找的基本工作流:

    1. 从数据库加载实体(或创建新实体)
    2. 让实体(及其所有关联分离(当EntitManager在HTTP请求结束时关闭时)
    3. 当下一个HTTP请求出现时,再次使用这些对象,在树中导航,而不必担心lazyinitexceptions。
    4. 调用一个方法,该方法保持在1-3期间所做的所有更改)

    使用来自Spring的OSIV过滤器和来自Wicket的IModel实现,我认为我已经存档了这一点。

    我基本上看到了两种可能的方法:

    a)加载实体和进入某个页面(用例)时所需的所有关联,让它们分离,在几个HTTP请求过程中根据需要添加/更改它们。然后在用户启动保存时重新附加它们(验证器将确保有效状态),并将它们提交到数据库。

    b)使用当前设置,但确保所有新添加的实体都设置了所有必需的字段(可能使用了一些向导组件)。对于每个merge(),我仍然拥有对数据库的所有更新,但希望数据库管理员不会意识到;)

    其他人如何在Web环境中使用JPA?我还有别的选择吗?