问题
I have a pretty simple mysql record like this:
+------+-------+-----------+
| id | name | password |
+------+-------+-----------+
| 1 | John | d0c91f13f |
+------+-------+-----------+
... ... ...
And here is its hibernate entity; nothing fancy
@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;
}
}
For convenience, I use Gson to parse the entity from json string which front-end passed in.
The json string for the record is like this:
{"id":1, "name":"John", "password":"d0c91f13f"}
then userEntity will be parsed from the json String:
UserEntity userEntity = gson.fromJson(userJson, UserEntity.class);
I can insert or update the user with Session.save(userEntity)
and Session.update(userEntity)
.
If every field is contained in the json string, then things seemed goes as expected.
But when some field, such as password
is omitted:
{"id":1, "name":"John Smith"}
which indicated that I should make a partial update and leave the omitted field not modified, things went wrong. Because
the parsing procedure will set password
to Null. and update it to the database.
So, is there a solution to partially update the record in this case?
Going through every field and setting fields one by one will be the last option; anything other than that?
Thanks in advance.
回答1:
If you know a particular entry exists, then fetching the entry before updating would fill the object with the existing values and you'd only change the values your Json provided. This avoids null updates like you describe.
If, however, the entry is new, then whatever is missing in the Json will be passed as null to the database.
回答2:
1,Suppose you can deserialized srcUserEntity by:
UserEntity srcUserEntity = gson.fromJson(userJson, UserEntity.class);
2, You can leverage spring's BeanUtil's copy properties method.
BeanUtils.copyProperties(srcUserEntity, desUserEntity, SpringBeanUtil.getNullPropertyNames(srcUserEntity));
3, In your Dao layer, just fetch the model from Database first, then update the properties needs to be updated only, lastly update. Refer to codes as below:
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, for getNullPropertyNames() method, please refer to [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))
}
来源:https://stackoverflow.com/questions/27578395/hibernate-partially-update-when-entity-parsed-with-json