【问题标题】:hibernate partially update when entity parsed with json使用 json 解析实体时休眠部分更新
【发布时间】:2015-02-19 02:50:22
【问题描述】:

我有一个非常简单的 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字符串中解析userEntity:

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

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

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

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

这表明我应该进行部分更新并且不修改省略的字段,但出现了问题。因为 解析过程会将password 设置为Null。并将其更新到数据库中。

那么,在这种情况下,有没有办法部分更新记录?

遍历每个字段并逐个设置字段将是最后一个选项;除此之外还有什么?

提前致谢。

【问题讨论】:

    标签: java mysql json hibernate sql-update


    【解决方案1】:

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

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

    【讨论】:

    • 你能具体解释一下吗? “获取”是什么意思?比如UserEntity user = gson.fromJson(json, UserEntity.class); session.get(UserEntity, userEntity.getId()); session.update(userEntity)?我会试试的。
    • 我的意思是您应该首先检索存储在数据库中的 UserEntity,然后对检索到的对象进行任何更改。完成后,更新它。由于您从数据库中获取了对象,因此您未更改的任何属性都将具有存储在数据库中的值并且不应更改。
    • 我知道这会奏效,但为了完成这项工作,我应该手动反序列化 json 字符串并使用反射(可能是?)根据它包含的字段设置属性,一些工作 gson.fromJson()已经完成了。
    • 对从 Json 重构对象的方法使用反射会起作用,是的。您还可以在使用 @PreUpdate 注释的 UserEntity 中放置一个方法,如下所示:@PreUpdate public void validateJsonInput(UserEntity entity)。参数是即将更新的对象;您可以获取此对象的 id 并在此方法中从数据库中检索原始 ID,并在此处执行所有相关检查,而无需在使用 Json 的类中进行反射。
    【解决方案2】:

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

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

    2、可以利用spring的BeanUtil的copy properties方法。

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

    【讨论】:

      猜你喜欢
      • 2011-12-15
      • 2013-07-24
      • 2019-06-22
      • 2016-12-20
      • 1970-01-01
      • 1970-01-01
      • 2023-01-07
      • 2018-10-24
      • 1970-01-01
      相关资源
      最近更新 更多