如何避免使用空值覆盖非空值?

时间:2011-09-19 15:35:46

标签: java hibernate jpa entitymanager

我正在使用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构建的对象的“密码”字段为空。我不希望密码字段被空值覆盖。有一种方法可以说“休眠”,如果你发现一个空值忽略它并且不覆盖数据库中保存的值?“。我无法相信这个看似简单的问题没有一个简单的解决方案。

5 个答案:

答案 0 :(得分:6)

我认为您的问题的根源是您从JSON解析中获取的对象从未在其中获得实际值。它是一个只设置了JSON中的值的bean。

您需要从数据库加载实体,然后将JSON中的非空字段设置为加载的实体。这样,只会设置JSON中提供的字段。

我建议使用某种类型的适配器在保存数据库版本之前“合并”(不是JPA合并)数据库版本和JSON版本。

添加@NotNull约束和Bean Validation将确保在尝试保存时值不为null。不幸的是,他们无法帮助您将值存入实体以进行保存。

答案 1 :(得分:2)

我有同样的问题。 我在this way中解决了这个问题。

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;
}
}

这显然是一种解决方法,但似乎工作顺利......在接下来的几天里,我想我会编写递归部分。

答案 2 :(得分:0)

为您的属性实施setter并在那里进行检查。

答案 3 :(得分:0)

检查Hibernate Validation项目,该项目可用于在DAO级别以及Spring Web layer上验证您的对象。

答案 4 :(得分:-1)

如果您的问题只是数据库,那么我建议您使用存储过程,检查该值是否为null,然后不更改现有值。这样你仍然可以发送一个空值,并且你的验证在服务器端更强大。