当使用json解析实体时,hibernate会部分更新

时间:2014-12-20 08:17:31

标签: java mysql json hibernate sql-update

我有一个非常简单的mysql记录,如下所示:

+------+-------+-----------+
| id   |  name | password  |
+------+-------+-----------+
| 1    | John  | d0c91f13f |
+------+-------+-----------+
 ...      ...     ...

这是它的休眠实体;没有什么花哨的

@Entity
@Table(name = "user", schema = "", catalog = "trade")
public class UserEntity{
     private long id;
     private String name;
     private String password;

     @Id
     @Column(name = "id")
     public long getId(){
          return id;
     }
     public void setId(long id){
          this.id = id;
     }

     @Column(name = "name")
     public String getName(){
          return name;
     }
     public void setName(String name){
          this.name = name;
     }

     @Column(name = "password")
     public String getPasswrod(){
          return password;
     }
     public void setPassword(String password){
          this.password = password;
     }
}

为方便起见,我使用Gson从前端传入的json字符串解析实体。
记录的json字符串是这样的:

{"id":1, "name":"John", "password":"d0c91f13f"}

然后将从json String解析userEntity:

UserEntity userEntity = gson.fromJson(userJson, UserEntity.class);

我可以使用Session.save(userEntity)Session.update(userEntity)插入或更新用户。

如果每个字段都包含在json字符串中,那么事情似乎就像预期的那样。 但是当省略某些字段时,例如password

{"id":1, "name":"John Smith"}

表示我应该进行部分更新并保留未修改的省略字段,出错了。因为 解析过程将password设置为Null。并将其更新到数据库。

那么,在这种情况下是否有部分更新记录的解决方案?

逐个浏览每个字段并设置字段将是最后一个选项;还有什么呢?

提前致谢。

2 个答案:

答案 0 :(得分:0)

如果您知道存在特定条目,则在更新之前获取条目将使用现有值填充对象,并且您只需更改Json提供的值。这样就可以避免像你描述的那样进行空更新。

但是,如果条目是新的,那么Json中缺少的任何内容都将作为null传递给数据库。

答案 1 :(得分:0)

1,假设您可以通过以下方式反序列化srcUserEntity:

UserEntity srcUserEntity = gson.fromJson(userJson, UserEntity.class);

2,您可以利用spring的BeanUtil复制属性方法。

BeanUtils.copyProperties(srcUserEntity, desUserEntity, SpringBeanUtil.getNullPropertyNames(srcUserEntity));

3,在你的Dao层中,只需先从数据库中获取模型,然后更新属性只需要更新,最后更新。请参阅以下代码:

Session currentSession =  sessionFactory.getCurrentSession();
UserEntity modelInDB = (UserEntity)currentSession.get(UserEntity.class, user.getId());
//Set properties that needs to update in DB, ignore others are null.
BeanUtils.copyProperties(productStatusModelForPatch, modelInDB, SpringBeanUtil.getNullPropertyNames(productStatusModelForPatch));
currentSession.update(modelInDB);

4,对于getNullPropertyNames()方法,请参考[How to ignore null values using springframework BeanUtils copyProperties? (Solved)

public static String[] getNullPropertyNames (Object source) {
final BeanWrapper src = new BeanWrapperImpl(source);
java.beans.PropertyDescriptor[] pds = src.getPropertyDescriptors();

Set<String> emptyNames = new HashSet<String>();
for(java.beans.PropertyDescriptor pd : pds) {
    Object srcValue = src.getPropertyValue(pd.getName());
    if (srcValue == null) emptyNames.add(pd.getName());
}
String[] result = new String[emptyNames.size()];
return emptyNames.toArray(result); 
}


// then use Spring BeanUtils to copy and ignore null
public static void myCopyProperties(Object, src, Object target) {
    BeanUtils.copyProperties(src, target, getNullPropertyNames(src))
}