Java基于点注解的嵌套POJO更新

4

我有一个嵌套的POJO结构定义,类似于这样:

public class Employee {
    private String id;
    private Personal personal;
    private Official official;
}

public class Personal {
    private String fName;
    private String lName;
    private String address;
}

public class Official {
    private boolean active;
    private Salary salary;
}

public class Salary {
    private double hourly;
    private double monthly;
    private double yearly;
}

我从一个带有点注释的服务中获取更新,以了解哪些值发生了改变,例如,

id change --> id=100
address change --> personal.address=123 Main Street 
hourly salary change --> official.salary.hourly=100

这个POJO结构可能会有3-4层深度。我需要查找这个传入的变化值并更新POJO中相应的值。做到最好的方法是什么?


如果您正在使用setter(甚至不使用),使用LambaMetafactory可能会导致最快的执行速度。这是我不太熟悉的事情,所以无法提供更多信息,只有这个这个。虽然您可能需要有关字段的其他信息(我认为这对于输入验证/过滤是必需的)。 - Gryphon
2个回答

1

这里有一个使用反射动态设置字段的快速方法。它肯定不是很干净,如果我是你,我会使用脚本引擎来实现(假设这样做是安全的)。

private static void setValueAt(Object target, String path, String value) 
        throws Exception {
    
    String[] fields = path.split("\\.");
    if (fields.length > 1) {
        setValueAt(readField(target, fields[0]), 
                path.substring(path.indexOf('.') + 1), value);
        return;
    }

    Field f = target.getClass()
            .getDeclaredField(path);
    f.setAccessible(true);
    f.set(target, parse(value, f.getType())); // cast or convert value first
}

//Example code for converting strings to primitives
private static Object parse(String value, Class<?> type) {
    if (String.class.equals(type)) {
        return value;
    } else if (double.class.equals(type) || Double.class.equals(type)) {
        return Long.parseLong(value);
    } else if (boolean.class.equals(type) || Boolean.class.equals(type)) {
        return Boolean.valueOf(value);
    }
    return value;// ?
}

private static Object readField(Object from, String field) throws Exception {
    Field f = from.getClass()
            .getDeclaredField(field);
    f.setAccessible(true);
    return f.get(from);
}

请注意,这段代码还有很多需要改进的地方(例如异常处理、空值检查等),尽管它似乎已经实现了你想要的功能(将输入按=分割以调用setValueAt()):

Employee e = new Employee();
e.setOfficial(new Official());
e.setPersonal(new Personal());
e.getOfficial().setSalary(new Salary());

ObjectMapper mapper = new ObjectMapper();
setValueAt(e, "id", "123");
// {"id":"123","personal":{},"official":{"active":false,"salary":{"hourly":0.0,"monthly":0.0,"yearly":0.0}}}

setValueAt(e, "personal.address", "123 Main Street");
// {"id":"123","personal":{"address":"123 Main Street"},"official":{"active":false,"salary":{"hourly":0.0,"monthly":0.0,"yearly":0.0}}}

setValueAt(e, "official.salary.hourly", "100");
// {"id":"123","personal":{"address":"123 Main Street"},"official":{"active":false,"salary":{"hourly":100.0,"monthly":0.0,"yearly":0.0}}}

0

如果您想创建允许您编辑字段的Java对象,可以使用public/default/protected访问修饰符指定对象字段。这将使您能够获取和设置字段,例如personal.addressofficial.salary.hours

这种方法通常被认为是不好的,因为对象不再封装,任何调用方法都可以操纵对象。如果这些字段没有使用getter和setter进行封装,则您的对象不再是一个POJO

public提供从任何地方访问的权限。

default提供从任何包访问的权限。

protected提供从包或子类访问的权限。

public class Employee {
    public String id;
    public Personal personal;
    public Official official;
}

public class Personal {
    public String fName;
    public String lName;
    public String address;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接