如何设置从Field(Reflection)到POJO的值?

时间:2018-10-24 11:31:23

标签: java java-ee reflection

我正在用Java动态地将值从ResultSet映射到POJO。我能够获取这些值,但不知道如何将这些值设置为pojo。有什么建议么?在此先感谢!

List<T> results = new ArrayList<>();
    while(resultSet.next())
    {
        T newObj = clazz.newInstance();
        for (Field field : clazz.getDeclaredFields()) 
        {
            String fieldName = field.getName().toLowerCase();
            if (columnNames.containsKey(fieldName)) 
            {
                final int index = columnNames.get(fieldName);
                field.set(fieldName, resultSet.getObject(index+1));
            }
        }
        results.add(newObj);
    }

3 个答案:

答案 0 :(得分:1)

Field.set的第一个参数(如果它是实例字段)必须是对象,或null字段的static。您改为通过fieldName,这显然是错误的。

所以改变

field.set(fieldName, resultSet.getObject(index+1));

field.set(newObj, resultSet.getObject(index+1));

当您的代码没有必要的访问权限时,可能需要在Field对象上设置“可访问”状态。但通常,您应该避免对ResultSet的每一行重复执行此类昂贵的操作。因此,您可以使用

List<T> results = new ArrayList<>();
Field[] theFields = clazz.getDeclaredFields();
// if overriding access right is needed:
AccessibleObject.setAccessible(theFields, true);

while(resultSet.next())
{
    T newObj = clazz.newInstance();
    for (Field field: theFields) 
    {
        Integer index = columnNames.get(field.getName().toLowerCase());
        if(index != null)
            field.set(newObj, resultSet.getObject(index+1));
    }
    results.add(newObj);
}

相反。甚至

List<T> results = new ArrayList<>();
Field[] theFields = clazz.getDeclaredFields();
// if overriding access right is needed:
AccessibleObject.setAccessible(theFields, true);

int numberOfFields = theFields.length;
int[] columnIndex = new int[numberOfFields];
for(int ix = 0; ix < numberOfFields; ix++) {
    Integer index = columnNames.get(theFields[ix].getName().toLowerCase());
    if(index != null) columnIndex[ix] = index + 1;
}

Constructor<T> con = clazz.getConstructor();

while(resultSet.next())
{
    T newObj = con.newInstance();
    for(int ix = 0; ix < numberOfFields; ix++)
        if(columnIndex[ix] != 0)
            theFields[ix].set(newObj, resultSet.getObject(columnIndex[ix]));
    results.add(newObj);
}

初始化起来比较复杂,但是会进一步减少循环内 repeated 的工作。请注意,此处使用Constructor不仅仅是一种优化,因为从Java 9开始,Class.newInstance()已被标记为已弃用

答案 1 :(得分:0)

您可以在设置值之前尝试以下行吗?

 field.setAccessible(true);

答案 2 :(得分:0)

完全使用FieldUtils方法来熟悉来自Apache Commons的writeDeclaredField软件包:

@Test
public void testWriteDeclaredNamedField() {
    FieldUtils.writeDeclaredField(object, "fieldName", "fieldValue");
    assertEquals("fieldValue", FieldUtils.readDeclaredField(object, "fieldName"));
}