當(dāng)用springdatajpa自帶save()進(jìn)行更新操作時(shí),會先在底層執(zhí)行merge()的一個(gè)動作,而執(zhí)行merge動作時(shí)根據(jù)entiy標(biāo)簽里面的@ID,也就是主鍵來區(qū)分的,所以正確的更新方式是先把對應(yīng)的entiy查詢出來,然后在更新某個(gè)字段。
這就引申出一個(gè)問題,假如我們直接使用實(shí)體對象來接收更新參數(shù),所以我們并不知道哪個(gè)字段被更改掉。這就涉及到新老數(shù)據(jù)的對比操作。雖然我們可以直接使用BeanUtils.copyProperties(oldEntiy,newEntiy);來進(jìn)行數(shù)據(jù)拷貝,但在不注意情況下就會出現(xiàn)丟失數(shù)據(jù)的情況。
如何防止這種情況呢。這里可以運(yùn)用java的反射機(jī)制來處理這種情況。話不多說,直接上代碼:
import java.beans.IntrospectionException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.Date;
/**
* @author lqyang
* @Title: SPRING-JPA-DATA 更新操作時(shí) 校驗(yàn)數(shù)據(jù)是否為空 解決處理BeanUtils.copyProperties(obj1,obj2);為空數(shù)據(jù)的處理
* @date 2018/8/217:00
*/
public class FieldUtil<T> {
private T entity;
public FieldUtil(T entity){
this.entity = entity;
}
/**
* 使用案例:
* SysUserEntity sysUserEntity = sysUserDao.findOne(user.getUserId());
* BeanUtils.copyProperties(sysUserEntity,user);
* if(sysUserEntity != null){
* for(Field f : user.getClass().getDeclaredFields()){
* f.setAccessible(true);
* if(f.get(user) == null){
* String name = f.getName();
* FieldUtil<SysUserEntity> fieldUtil = new FieldUtil<>(user);
* fieldUtil.doInitEntity(name,sysUserEntity);
* }
* }
* sysUserDao.save(user);
* }else {
* user.setUserId(StringUtil.uuid());
* sysUserDao.save(user);
* }
* @param methodName
* @param object
* @throws InvocationTargetException
* @throws IllegalAccessException
* @throws NoSuchFieldException
* @throws IntrospectionException
*/
public void doInitEntity(String methodName,Object object) throws InvocationTargetException, IllegalAccessException, NoSuchFieldException, IntrospectionException {
//根據(jù)傳入的屬性名稱構(gòu)造屬性的set方法名
String str = methodName.substring(0, 1).toUpperCase()+methodName.substring(1);
String methodNameNew = "set"+str;
Method[] methods = entity.getClass().getMethods();
for(Method method:methods){
//如果方法同名則執(zhí)行該方法(不能用于實(shí)體中有重載方法的情況)
if(methodNameNew.equals(method.getName())){
Class<?>[] clazz = method.getParameterTypes();
String type = clazz[0].getName();
if(type.equalsIgnoreCase("java.lang.String")){
Field field = object.getClass().getDeclaredField(methodName);
field.setAccessible(true);
if(field.get(object) != null){
method.invoke(entity,(String)field.get(object));
}
}
else if(type.equalsIgnoreCase("java.util.Date")){
Field field = object.getClass().getDeclaredField(methodName);
field.setAccessible(true);
if(field.get(object) != null){
method.invoke(entity, (Date)field.get(object));
}
}
else if(type.equalsIgnoreCase("java.lang.Integer")){
Field field = object.getClass().getDeclaredField(methodName);
field.setAccessible(true);
if(field.get(object) != null){
method.invoke(entity, new Integer((Integer) field.get(object)));
}
}
else if(type.equalsIgnoreCase("java.lang.Float")){
Field field = object.getClass().getDeclaredField(methodName);
field.setAccessible(true);
if(field.get(object) != null){
method.invoke(entity, new Float((Float) field.get(object)));
}
}
else if(type.equalsIgnoreCase("java.lang.Boolean")){
Field field = object.getClass().getDeclaredField(methodName);
field.setAccessible(true);
if(field.get(object) != null){
method.invoke(entity, new Boolean((Boolean) field.get(object)));
}
}
else if(type.equalsIgnoreCase("java.math.BigDecimal")){
Field field = object.getClass().getDeclaredField(methodName);
field.setAccessible(true);
if(field.get(object) != null){
method.invoke(entity, (BigDecimal) field.get(object));
}
}
}
}
}
}
使用案例
@Transactional(rollbackFor = Exception.class)
public void updateUser(SysUserEntity user)throws Exception {
SysUserEntity sysUserEntity = sysUserDao.findOne(user.getUserId());
//BeanUtils.copyProperties(sysUserEntity,user);
if(sysUserEntity != null){
for(Field f : user.getClass().getDeclaredFields()){
f.setAccessible(true);
if(f.get(user) == null){
String name = f.getName();
FieldUtil<SysUserEntity> fieldUtil = new FieldUtil<>(user);
fieldUtil.doInitEntity(name,sysUserEntity);
}
}
sysUserDao.save(user);
}
}