【问题标题】:JSF Form for an Entity -- Hot editing?实体的 JSF 表单——热编辑?
【发布时间】:2011-10-31 01:49:21
【问题描述】:

我正在编写一个 JSF 2.0 表单来编辑 JPA @Entity 对象。我有一个支持 bean,它有一个实体的 get 方法,它从 EntityManager 中获取。到目前为止一切顺利。

问题是用户正在编辑的实体对象是否可以被应用程序的其他部分访问?换句话说,如果其他人调用该记录,在我通过 EntityManager 将记录合并回数据库之前,他们是否看到字段更改?还是他们得到了不同的实例。

这很重要的原因是用户可以输入各种不良数据。 backing bean完成的验证阶段不会调用merge()所有的错误都会被清除,但是在那之前呢?

如果这是一个常见的例子,我该如何避免这个问题?

【问题讨论】:

    标签: jsf jsf-2 jpa-2.0


    【解决方案1】:

    问题是用户正在编辑的实体对象是否可以被应用程序的其他部分访问?换句话说,如果其他人调用该记录,在我通过 EntityManager 将记录合并回数据库之前,他们是否看到字段更改?还是他们得到了不同的实例。

    JSF 使用的实体实例将是一个分离的实体实例。它不属于持久性上下文。每个客户端/用户还将收到它自己的分离实体实例。

    这很重要的原因是用户可以输入各种不良数据。 backing bean完成的验证阶段不会调用merge()所有的错误都会被清除,但是在那之前呢?

    当您调用EntityManager.merge 将分离实体的内容与持久性上下文合并时,将发生任何无效数据的合并。如果您从未调用过merge,那么实体的修改内容将永远不会进入持久化上下文。

    如果这是一个常见的例子,我该如何避免这个问题?

    您始终可以通过在将实体与持久性上下文合并之前验证实体的状态来避免这种情况。您可以在 JSF 和 JPA 中使用 bean 验证来防止这种情况,尽管您通常只会在一层中执行此操作,以防止冗余检查。但是,如果您为 bean 验证约束指定了验证组以区分表示约束和持久性约束,那么您应该在两个层中都使用 bean 验证。请记住,一旦 bean 的内容与持久性上下文成功合并,除了事务回滚或refresh/clear 之外,您无法撤消此更改。持久化上下文。

    【讨论】:

    • 感谢您的澄清。如果 javadoc 提到 getSingleResult() 返回一个分离的实体,那就太好了。我假设 getResultList() 也是如此。
    • 当实体不再是持久化上下文的一部分时,就会发生实体的分离。它通常在 EntityManager 离开事务上下文时自动发生,即当事务提交或回滚时,或者在您调用 EntityManager.detach 时显式发生。 Query.getSingleResultQuery.getResultList 将始终返回托管实体。当事务结束时,这个被管实体变成一个分离的。
    • 您会在OpenEJB concepts guide 中以通俗易懂的方式解释这些概念。
    【解决方案2】:

    补充Vineet的正确答案:

    您的支持 bean 可能会返回一个附加实体,例如,如果您使用带有扩展持久性上下文的有状态会话 bean (EJB)。

    但是在这种情况下,您仍然不会冒并发问题的风险,因为持久性上下文的每个实例都会返回附加实体的唯一实例(唯一性:实例不与其他现有持久性上下文共享)。

    此外,如果发生任何类型的验证错误,JSF 不会将更改推送到模型(在本例中为附加的 JPA 实体)。因此,只要您正确设置了验证(bean 验证或常规 JSF 验证),就不会有“污染”实体的风险。

    另外,请注意,对于附加的案例,您不必调用 merge(),因为这会在上下文关闭时自动发生,因此您可以“关闭”有状态 bean。

    也就是说,常见的情况是 Vineet 描述了您在哪里获得了一个分离的实体。

    【讨论】:

      猜你喜欢
      • 2014-06-08
      • 2019-08-24
      • 1970-01-01
      • 2012-03-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-22
      • 1970-01-01
      相关资源
      最近更新 更多