利用Java反射解决Spring Data JPA繁琐更新操作

来源:互联网 发布:淘宝店铺转让怎么弄 编辑:程序博客网 时间:2024/05/18 00:00

场景再现

更新描述

  • 利用JPA进行更新时,通常是传入一个带id的对象
  • 拿id对数据库进行查询,拿到实体对象
  • 修改实体对象中的值,对于null的给予忽略

对象长这样

public class DailyCategory {    private int id;    private Integer merchantId;    private String name;    private Timestamp createTime;    private Timestamp updateTime;    //省略getter和setter方法...}

更新的写法

public ServerResponse updateCategory(DailyCategory category) {        Integer categoryId = category.getId();        DailyCategory rawCategory = categoryDao.findOne(categoryId);        //进行更新操作            if (category.getMerchantId() != null) {               rawCategory.setMerchantId(category.getMerchantId());        }        if (StringUtils.isEmpty(category.getName()))) {            rawCategory.setName(category.getName());        }}

问题来了

如果有category有10个字段,那我岂不是要写10个if?
而且每个更新的对象都要写。

解决方法

  • 基于Spring Data JPA的特性,从数据库取出来的对象,只要修改了其字段便是修改了数据库。
  • 函数形参一般情况下都是引用传递
  • getDeclaredMethods可以获得所有public修饰的方法
  • Method.invoke(对象, 参数)可以执行指定对象的指定方法
  • 原理就是:调用newObject的getOOXX方法获取该值,判断不为空的话,调用rawObject的setOOXX方法,实现改变rawObject的值
  • 一次遍历即可完成更新操作,对任意对象均可实现更新
public boolean updateNotNullField(Object rawObject, Object newObject) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {        //如果连个对象不一致。不进行更新字段值的操作        if (rawObject.getClass().getName() != newObject.getClass().getName()) {            return false;        }        //获取原始对象中的所有public方法        Method[] methods = rawObject.getClass().getDeclaredMethods();        //用于提取不包含指定关键词的方法        String regExpression = "^(get)(?!Id|CreateTime)(\\w+)";        Pattern pattern = Pattern.compile(regExpression);        Matcher m;        for (Method method : methods) {            m = pattern.matcher(method.getName());            //正则匹配以get开头,后面不能匹配Id、CreateTime这两个单词的方法            if (m.find()) {                Object o = method.invoke(newObject, null);                //忽略值为空的字段                if (o == null) {                    continue;                }                //取出get方法名后面的字段名                String fieldName = m.group(2);                //找到该字段名的set方法                Method rawMethod = rawObject.getClass().getMethod("set" + fieldName, method.getReturnType());                //调用实体对象的set方法更新字段值                rawMethod.invoke(rawObject, o);            }        }        return true;    }

END

不熟悉Spring Data JPA,如有更好的方法还望不吝赐教~

原创粉丝点击