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