PlayFramework 2.5 - 使用反射更新 Ebean

PlayFramework 2.5 - Ebean update using reflection


我正在使用 Play framework 2.5 和 Ebean 作为 ORM 开发一个带有内联编辑器的网站,我有一个新闻部分,管理员可以在其中编辑每条新闻(编辑内联字段,如标题、内容等)。
为此,我将每个可以用等于新闻模型字段的 id 修改的 html 元素设置为(例如,映射字段标题的 html 元素将具有 id="title" ), 然后当我从客户端接收数据时,我在控制器上使用反射将每个内容映射到正确的新闻字段。

这是代码(EditContent 是一个 object,其中包含每个修改内容的 ID 和 htmlContent 等信息):

News news = News.find.byId(newsId);

for(EditContent content : pageContents.contents) {
    Field field = news.getClass().getField(content.cssId);
    field.setAccessible(true);
    field.set(news, content.htmlContent);
}

news.update();

问题是似乎执行了更新,但实际上并没有在数据库上更新值。使用调试器,我检查了 object 新闻,我可以看到字段已正确修改,但更新对数据库没有影响。
另外,我注意到相同的代码使用:

News news = new News()
...
//reflection to save modifed contents in the new object
...
news.save()

如我所料,在数据库中保存了一个新行。

有什么想法吗?

提前感谢您的帮助!

您正在设置字段值,而不是调用 setter 方法。

因此对于 update() ... Ebean 不知道哪些属性已更改 - 它认为 none 已更改。

Play 通过增强将字段 put 调用修改为方法调用。所以这可能就是您认为这些反射场设置值可能有效的原因。

所以基本上,正如@Rob Bygrave 所说...应该在此处调用 setter 方法而不是直接设置字段值,因为如果将值设置为相应的值,ebean 将忽略新值直接打野。 play framework 似乎遵循了Java bean 约定,所以基本上我们可以猜到set name 叫什么。 这是动态更新用户信息的示例代码:

private final String[] userUpdatableNames = { "name", "password", "allowGPS" };

...

        JsonNode dateForm = request().body().asJson();
        Field field;
        Class<?> type;
        Method method;      
        for (int i = 0; i < userUpdatableNames.length; i++) {
            if (isArgs[i]) {
                        try {
                            field = target.getClass().getDeclaredField(userUpdatableNames[i]);
                            type = field.getType();
                            Method method = target.getClass().getMethod("set" + initialUpperize(userUpdatableNames[i]), type);
                            method.invoke(target, convert(type,dateForm.findValue(userUpdatableNames[i]).textValue()));
                            }catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException
| NoSuchMethodException | InvocationTargetException e) {
                            return internalServerError(Json.toJson("Invoke exception"));
                           }
            } 
      }

...

public String initialUpperize(String str) {
    return str.substring(0, 1).toUpperCase() + str.substring(1);
}

...

private Object convert(Class<?> targetType, String text) {
    PropertyEditor editor = PropertyEditorManager.findEditor(targetType);
    editor.setAsText(text);
    return editor.getValue();
}

其中isArgs是一个布尔数组,用于标记该字段是否在Json正文中...

谢谢