分离Formbacking和数据库支持的模型。什么是有效的方法

时间:2014-05-23 08:51:15

标签: playframework playframework-2.2

最后几天我阅读了很多关于游戏示例建议构建游戏应用程序方式的文章/评论/问题。这些示例建议使用相同的Model / Class来支持数据库和表单。但我有一个问题。表单篡改和混乱代码,用于处理提交表单的更新(仅限模型的某些字段)... 但是当我搜索这些问题的解决方案时,我经常会遇到一些github问题,其中游戏核心团队表示,使用相同类进行Formbacking和数据库的人,这是他们自己的错。(https://github.com/playframework/playframework/issues/2358 )他们的评论暗示我们应该使用分离的模型进行formbacking和数据库。 同样,这与示例所说的完全相反。

所以“我”提出了一个“解决方案”(在阅读了伟大的文章https://github.com/ics-software-engineering/play-example-form之后)

所以这是我的方法。

假设我有一个用户模型。用户有一些字段应该由用户编辑(因此他们应该进入表单)和一些字段,这些字段不应该由简单的表单编辑,如“isAdmin”或创建/修改等等。

所以我创造了一个正常的游戏!具有所需字段的用户类,以及实体注释等。就像普通类一样,但没有验证。

我创建了一个“UserFormModel”。这是一个没有任何实体/数据库注释/属性的POJO,但带有Validations(注释和validate()方法)。

现在我的应用程序使用此UserFormModel来表示表单中的用户。它具有来自实际用户的字段子集。 现在,甚至表单篡改也不会影响我的后端用户类中的非公共字段。这样做的缺点是,每当我想为用户显示/处理表单时,我必须将数据从UserFormModel传输到实际的用户类。对于小字段,这不是问题。

对于此转移,我实施了

public static User makeInstance(UserFormModel formData) {
    User user;
    if (formData.id != null) {
        user = findById(formData.id);
        user.setTestString(formData.testString);
    } else {
        user = new User();
    }
    return user;
}
用户类中的

从表单模型创建用户(更新现有的on(id存在)或实例化新的用户)

UserFormModel

也是如此
    public UserFormModel prefillFormModel(User user) {
    this.id = user.getId();
    this.testString = user.getTestString();
    this.jobs = user.getJobs();
    this.mails = user.getMails();
    return this;        
}

这将使用实际用户的“公共”字段预填充Formbacking模型

您如何看待这种方法?

作为一项改进,如果UserFormModel实际上只是实际用户的一个字段子集,那么我正在尝试使用反射将数据从一个模型传递到另一个模型。 在我想从UserFormModel创建一个User对象的情况下,我可以迭代UserFormModel中的所有公共字段,并调用实际用户的相应setter(如果它遵循java bean约定,我可以推断出名称来自其名称的字段的setter) 这将减少每个模型中所需的样板代码,以便来回传输数据。

编辑:在我睡了一个晚上之后,我提出了一个问题:任何人都可以用嵌套形式处理这种设计方法。假设我想编辑用户,并同时添加一些新的邮件对象。使用普通播放这不是问题,因为我的用户有一个字段列表,因此它知道如何处理它,包括@Valid注释。但是当我有一个UserFormModel时会出现问题,因为这只会知道没有注释验证的Mail-Model(因为我想将数据域对象与表单模型分开)。我该怎么办?!在UserFormModel中声明List而不是List,并让转换回真实邮件发生在实际用户模型的邮件设置器方法中?我认为这样可行,但它增加了一大堆杂乱......

1 个答案:

答案 0 :(得分:1)

这是一个难题。 Ruby on Rails有一个类似的表单支持模型方法。但是,动态语言中的调整和自定义更容易。

你的方法似乎很合理。您可以使用反射或代码生成来编写字段复制代码。注释适用于大多数验证,但Play也会寻找一个validate()方法,您可以在其中放置自定义代码。