如何在多个请求中保持实体(或其关联)附加到当前持久性上下文(使用Wicket& JPA)? [英] How do I keep entities (or their associations) attached to the current persistence context across multiple requests (using Wicket & JPA)?

查看:153
本文介绍了如何在多个请求中保持实体(或其关联)附加到当前持久性上下文(使用Wicket& JPA)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在研究基于Wicket的Java EE上的Web应用程序。

I am working on a Wicket-based web app on Java EE.

我正试图找到一种方法来确保任何用作模型对象的实体始终是在Wicket尝试呈现任何组件之前附加到当前的EntityManager。这样,当组件从其模型中获取数据时,实体可以根据需要延迟加载数据。

I am trying to find a way to ensure that any entities used as model objects are always attached to the current EntityManager before Wicket tries to render any components. This way, when the components grab data from their model, the data can be lazily-loaded by the entity as needed.

有很多教程,有些这里的帖子,指的是LoadableDetachableModels(LDM)作为解决方案。当我们不需要保持任何状态中间请求时,这对我们有用。在这些情况下,无论何时呈现页面,LDM都将从数据库加载所需实体的最新版本。

There are lots of tutorials out there, and some posts on here, referring to LoadableDetachableModels (LDM) as the solution. This has worked for us when we don't need to keep any state in-between requests. In these cases, whenever the page is rendered, the LDM will load the most recent version of the required entity from the database.

但是,有时用户需要在保存数据之前,通过多个步骤编辑有状态形式的数据,因此模型需要将实体保留在未保存状态。 LDM会在每一步都有效地消除用户的更改。

However, there are times when a user needs to edit data in a stateful form via multiple steps before she saves the data, so the model needs to retain the entity in its 'unsaved' state. An LDM would effectively wipe out the user's changes on every step.

到目前为止,我们一直在使用一个模型,在需要时将实体与持久化上下文合并。这是一个简化版本:

So far, we have been using a model that merges the entity with the persistence context when needed. Here is a simplified version:

public final class DetachableMergingModel<E extends Identifiable> implements IModel<E> {

    private E entity;
    private boolean attached = false;

    public DetachableMergingModel(E entity) {
        this.entity = entity;
    }

    @Override
    public E getObject() {
        if (!attached) {
            attached = true;
            // Non-transactional method merges entity with persistence context 
            // but does not flush any data to database
            entity = getRepository().merge(entity);
            }
        }
        return entity;
    }

    @Override
    public void setObject(E entity) {
        this.entity = entity;
    }

    @Override
    public void detach() {
        // This ensures that the next call to getObject() will merge the entity with 
        // the persistence context
        attached = false;
    }
    /* ... */
}

我们的EntityManager由GlassFish注入,它跨越整个servlet请求,因此当一个实体附加到持久化上下文时,它将保持连接直到页面呈现后。

Our EntityManager is injected by GlassFish and it spans a whole servlet request, so when an entity is attached to the persistence context, it will stay attached until after the page has been rendered.

上面的模型处理了实体已经被持久化并且正在被编辑的情况。只要页面上的组件在此模型上调用getObject(),模型就会将实体与持久化上下文合并,我们可以自由地导航实体的整个对象图,而不会抛出任何LazyInitializationExceptions。

This Model above takes care of situations where the entity is already persisted and is just being edited. Whenever a component on the page calls getObject() on this model, the Model will merge the entity with the persistence context, and we are free to navigate the whole object graph of the entity without throwing any LazyInitializationExceptions.

但是,在实体是新的且尚未持久化的情况下,我们无法使用此模型,因为实体尚未准备好合并。当用户创建新实体时,通常会出现这种情况,并且仍然需要通过表单使用值填充它。在这种情况下,我们希望有相同的自由导航实体的对象图(因为已经设置了一些关联,例如实体的父对象),而不用担心LazyInitializationException。

However, in a situation where the entity is new and has not been persisted, we cannot use this Model because the entity is not ready to be merged yet. This is often the case when the user is creating a new entity, and still needs to populate it with values via the form. In this case, we want to have the same freedom navigating the object graph of the entity (as some associations have already been set, such as the entity's parent), without fear of a LazyInitializationException.

描述了类似的解决方案此处(选项#3),但它不包含上述'新实体'用例。

A similar solution is described here (option #3), but it does not cover the 'new entity' use-case described above.

有没有人遇到过这个用例?你是怎么解决的?是否有更好的方法将Wicket与JPA集成而不是通过自定义IModel实现?

Has anyone come across this use-case? How did you solve it? Is there a better way to integrate Wicket with JPA than through custom IModel implementations?

推荐答案

我这样的情况我通常会创建一个DTO保留创建实体所需的所有数据。
如果您需要引用现有实体 - 将它们作为单独的模型传递给您的表单/面板。提交表单后,您可以:

I cases like this I usually create a DTO keeping all the data I need to create an entity. If you need to reference existing entities - pass them to your forms/panels as separate models. When the form is submitted you can then:


  • 执行验证

  • 从中创建新实体已编辑的DTO

  • 将对存储在这些单独的LDM模型中的其他实体的引用注入。

  • 保留实体。

  • perform the validation
  • create a new entity from DTO that was edited
  • inject references to other entities that you have stored in those separate LDM models.
  • persist the entity.

这有点麻烦,但确实有效。

It's a bit of hassle but does actually work.

跨越多个请求的对话不可用在纯粹的检票口,可能永远不会 - 这不是检票口的区域。

Conversations spanning multiple requests are not available in pure wicket and probably will never be - this is not wicket's area.

Seam支持长时间的对话,它确实支持wicket(我从未使用过seam - 我无法就此进行建议)。

Seam supports long conversations and it does support wicket (I have never used seam - I cannot advice you on this one).

这篇关于如何在多个请求中保持实体(或其关联)附加到当前持久性上下文(使用Wicket&amp; JPA)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆