micronaut 原生的情况
更新所有值不管是否为null
笔者接口实现逻辑
将数据库中的值查出 ,将非空值覆盖到数据库中查出的值上,最后调用update接口
代码
import io.micronaut.aop.MethodInvocationContext;
import io.micronaut.aop.chain.MethodInterceptorChain;
import io.micronaut.core.annotation.Internal;
import io.micronaut.data.intercept.RepositoryMethodKey;
import io.micronaut.data.intercept.UpdateEntityInterceptor;
import io.micronaut.data.jpa.operations.JpaRepositoryOperations;
import io.micronaut.data.operations.RepositoryOperations;
import io.micronaut.data.repository.CrudRepository;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import javax.persistence.EntityManager;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
/**
* @author fuchanghai
*/
@Internal
public class UpdateService implements UpdateEntityInterceptor {
private final JpaRepositoryOperations jpaOperations;
protected UpdateService(RepositoryOperations operations) {
if (operations instanceof JpaRepositoryOperations) {
this.jpaOperations = (JpaRepositoryOperations) operations;
} else {
throw new IllegalStateException("Repository operations must be na instance of JpaRepositoryOperations");
}
}
@Override
public Object intercept(RepositoryMethodKey methodKey, MethodInvocationContext context) {
MethodInterceptorChain chain = (MethodInterceptorChain) context;
Object[] parameterValues = chain.getParameterValues();
for (int i = 0; i < parameterValues.length; i++) {
if (chain.getTarget() instanceof CrudRepository) {
try {
//此处可改进根据自定义注解获取id值
Field id = parameterValues[i].getClass().getDeclaredField("id");
id.setAccessible(true);
Optional byId = ((CrudRepository) chain.getTarget()).findById(id.get(parameterValues[i]));
String[] nullProperties = getNullProperties(parameterValues[i]);
Object target = byId.get();
BeanUtils.copyProperties(parameterValues[i], target, nullProperties);
EntityManager entityManager = jpaOperations.getCurrentEntityManager();
entityManager.merge(target);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
return chain;
}
private static String[] getNullProperties(Object src) {
BeanWrapper srcBean = new BeanWrapperImpl(src);
PropertyDescriptor[] pds = srcBean.getPropertyDescriptors();
Set<String> properties = new HashSet();
PropertyDescriptor[] var4 = pds;
int var5 = pds.length;
for (int var6 = 0; var6 < var5; ++var6) {
PropertyDescriptor propertyDescriptor = var4[var6];
String propertyName = propertyDescriptor.getName();
Object propertyValue = srcBean.getPropertyValue(propertyName);
if (null == propertyValue) {
srcBean.setPropertyValue(propertyName, (Object) null);
properties.add(propertyName);
}
}
return (String[]) properties.toArray(new String[0]);
}
}
解决问题经过
1.刚开始在国内搜 搜不到
2.在国外网站以及stack overflow上也没找到
3.对照着spring-jpa的尿性绝对有个默认实现类,去github 上找到对应的接口,发现了UpdateEntityInterceptor 这个接口
4,@Inject EntityManager 发现是null
5迫不得已
6.作者给例子
当时是12 天前才写的那个例子,怪不得网上搜不到,
7最终 上面的那个类才自己实现了