2016-07-29 3 views
0


Я разрабатываю веб-сайт с встроенным редактором, используя Play Framework 2.5 и Ebean в качестве ORM, и у меня есть раздел новостей, в котором администратор может редактировать каждую новость (редактирование полей inline, таких как как заголовок, содержание и т. д.).
Для этого я устанавливаю каждый элемент html, который может быть изменен с идентификатором, равным полю модели новостей (например, элемент html, отображающий заголовок поля, будет иметь id = "title"), а затем, когда я получаю данные из клиент, я использую отражение на контроллере для сопоставления каждого контента с правильным полем новостей.PlayFramework 2.5 - Обновление Ebean с использованием отражения

Вот код (EditContent это объект, который содержит информацию, как Ид и 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(); 

Проблема заключается в том, что обновление, кажется, выполнены, но на самом деле значения не обновляется на db. Используя отладчик, я осмотрел новости объекта, и я вижу, что поля были правильно изменены, но затем обновление не влияет на db.
Кроме того, я заметил, что тот же самый код с помощью:

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

работает как я ожидаю, сохранение новой строки в базе данных.

Любая идея?

Заранее благодарю вас за помощь!

+0

Зачем вам нужно использовать отражение? Кроме того, по мере изменения объекта EditContent, вы пытались сохранить его вместо новостей? – Salem

+0

Я хочу использовать отражение, чтобы избежать явного задания каждого поля новостей (и для редактирования контроллера кода на случай изменения модели).Я не могу сохранить EditContent, потому что это только подмножество полей новостей, в частности, оно содержит только измененные поля, а также содержит другие данные относительно html, такие как cssId – lbaggi

+0

Привет @lbaggi, как вы решили проблему? Можно ли даже заставить его работать с отражениями? Я бы очень признателен за ваш ответ, потому что у меня такая же проблема. Спасибо –

ответ

0

Вы устанавливаете значения полей, а не вызываете метод сеттера.

Итак, для обновления() ... Ebean не знает, какие свойства были изменены - он думает, что никто не изменился.

Воспроизведение изменяет поле, помещая вызовы в вызовы методов посредством расширения. Поэтому, возможно, вы считаете, что эти значения значений поля отражения могут работать.

+0

Другими словами, нет способа обновить Entity, используя отражение? Я должен установить каждое поле напрямую (и пусть Ebean обрабатывает созданные генераторы/сеттеры)? Почему вместо этого встраивается новый объект? – lbaggi

+0

> Другими словами, нет способа обновить сущность с использованием отражения? ... Нет. Это означает, что Ebean перехватывает методы (сеттеры) и что вы не можете перехватить поле отражения. –

+0

Вы понимаете, что Ebean ожидает геттеров и сеттеров (ну, методы). Это игра, которая способствовала использованию публичных полей ... и усовершенствованию Play, которое преобразует эти вызовы getfield/putfield публичного поля в вызовы методов ... это Play делает это, а не Ebean. –

0

Так что, в основном, как сказал @Rob Bygrave ... Здесь следует вызывать метод setter, а не устанавливать значение поля непосредственно, потому что ebean будет игнорировать новое значение, если вы установите значение в соответствующее поле напрямую. Кажется, что игровая инфраструктура после соглашения Java bean, поэтому в основном мы можем догадаться, что назвало имя набора. Ниже приведен пример кода для обновления информации пользователя динамически:

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 теле ...

Благодаря