Объект JPA, измененный отражением, не объединенный менеджером объекта

Мне нужно проверить, отличается ли моя действительная сущность от старой.

Я использую отражение, потому что мой метод должен быть стандартизирован.

Для каждого столбца я обновляю значение тогда и только тогда, когда оно не равно нулю (потому что я читаю его из CSV, и столбец может быть не указан).

for(Field column : fields){
   column.setAccessible(true);
   Object newValue = column.get(myObject);
   if( newValue != null && !newValue.equals(column.get(oldObject))){
      column.set(oldObject, newValue);
   }
}

this.entitymanager.merge(oldObject)

Если я делаю подобные изменения, запрос UPDATE не выполняется.

Если я изменю значение обычным способом oldobject.setValue(newValue) запрос выполнен, и запись обновлена.

Почему менеджер сущностей не выполняет запрос UPDATE, если я изменяю значение с помощью отражения?

2 ответа

Просто найдите хорошую информацию о таком поведении в этом:

По умолчанию при использовании weaving/agent EclipseLink использует отслеживание изменений атрибутов для обнаружения изменений. Это не обнаружит изменения, сделанные через доступ к отражающему полю (хотя доступ к методу в порядке).

Вы можете изменить значение по умолчанию с помощью аннотации @ChangeTracking на deferred, которая будет обнаруживать изменения, сделанные с помощью отражения. т.е. @ChangeTracking(ChangeTrackingType.DEFERRED)

Вы также можете отключить переплетение или отслеживание изменений в файле persistence.xml, используя "eclipselink.weaving.changetracking"="false"

Итак, есть несколько решений, которые можно попробовать:

  1. Использовать рефлексивный метод доступа
  2. Измените ChangeTracking на отложенный или даже отключите его
  3. Отключить ткачество

Спасибо @Ken Chan ответу, я исправляю метод, используя геттеры и сеттеры.

for(Field column : columns){
   Method mSet = myclass.getMethod("set"+ StringUtils.capitalize(column.getName()), column.getType());
   Method mGet = myclass.getMethod("get"+ StringUtils.capitalize(column.getName()));
   Object newValue = mGet.invoke(articolo);
   if( newValue != null && !newValue.equals(mGet.invoke(old))){
        mSet.invoke(old, newValue);
   }
 }

Я должен обратить внимание на название методов. Если субъект имеет свойство descriptionдолжно быть также getDescription() а также setDescription(),

Теперь работает

Другие вопросы по тегам