Как избежать перезаписи ненулевых значений нулевыми значениями? - PullRequest
4 голосов
/ 19 сентября 2011

Я использую Spring MVC для получения JSON от клиента и автоматического создания объекта из него.Проблема в том, что клиент не отправляет на сервер все поля, которые есть в сущности, но некоторые поля имеют нулевое значение и перезаписывают существующие значения, вызывая userDao.persist (user).Например, у меня есть эта сущность:

@Entity
public class User {

    @Id @GeneratedValue
    private int id;

    private String username;
    private String password;
    private String email;

Но пользователь никогда не посылает мне пароль, поэтому у объекта, построенного из JSON, поле «пароль» пусто.Я не хочу, чтобы поле пароля перезаписывалось нулевым значением.Есть способ сказать hibernate «если вы найдете нулевое значение, игнорируйте его и не перезаписывайте значение, сохраненное в базе данных?».Я не могу поверить, что не существует простого решения этой, казалось бы, простой проблемы.

Ответы [ 5 ]

6 голосов
/ 19 сентября 2011

Я думаю, что источником вашей проблемы является то, что объект, который вы возвращаете из анализа JSON, никогда не содержал в себе реальных значений. Это bean-компонент, в котором есть только те значения, которые есть в вашем JSON.

Вам необходимо загрузить вашу сущность из БД, а затем установить ненулевые поля из вашего JSON в загруженную сущность. Таким образом будут заданы только поля, предоставленные в JSON.

Я рекомендую какой-нибудь адаптер для «слияния» (а не слияния JPA) версии БД и версии JSON перед сохранением версии БД.

Добавление ограничения @NotNull и Bean Validation позволит убедиться, что значения не равны NULL при попытке сохранения. К сожалению, они не помогут вам сохранить значения в сущности для сохранения.

2 голосов
/ 24 сентября 2015

У меня та же проблема. Я решил это в таким образом .

import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import java.lang.reflect.Field;
import java.util.Hashtable;



public class Updater {

private final static Logger log = LogManager.getLogger(Updater.class);

public static <E> E updater(E oldEntity, E newEntity) {

    Field[] newEntityFields = newEntity.getClass().getDeclaredFields();
    Hashtable newHT = fieldsToHT(newEntityFields, newEntity);

    Class oldEntityClass = oldEntity.getClass();
    Field[] oldEntityFields = oldEntityClass.getDeclaredFields();

    for (Field field : oldEntityFields){
        field.setAccessible(true);
        Object o = newHT.get(field.getName());
        if (o != null){
            try {
                Field f = oldEntityClass.getDeclaredField(field.getName());
                f.setAccessible(true);
                log.info("setting " + f.getName());
                f.set(oldEntity, o);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            }
        }

        }

    return oldEntity;
    }



private static Hashtable<String, Object> fieldsToHT(Field[] fields, Object obj){
    Hashtable<String,Object> hashtable = new Hashtable<>();
    for (Field field: fields){
        field.setAccessible(true);
        try {
            Object retrievedObject = field.get(obj);
            if (retrievedObject != null){
                log.info("scanning " + field.getName());
                hashtable.put(field.getName(), field.get(obj));
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
    return hashtable;
}
}

Это явно обходной путь, но, похоже, он работает гладко ... в следующие дни я думаю, что напишу рекурсивную часть.

0 голосов
/ 19 сентября 2011

Если вашей проблемой является только база данных, то я предлагаю вам использовать хранимую процедуру, которая проверяет, является ли это значение нулевым, а затем не изменяет существующее значение. Таким образом, вы все равно можете отправить нулевое значение, и ваша проверка выполняется на стороне сервера, которая является более надежной.

0 голосов
/ 19 сентября 2011

Check Hibernate Validation проект, который можно использовать для проверки вашего объекта на уровне DAO, а также на Spring Web layer .

0 голосов
/ 19 сентября 2011

Реализуйте сеттеры для ваших атрибутов и выполняйте там проверки.

...