简体   繁体   中英

How to set the values from Field(Reflection) to POJO?

I am working on dynamically mapping values from ResultSet to POJO in java. I am able to get the values but don't know how to set those value to the pojo. Any suggestions? Thanks in Advance !!

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);
    }

The first argument to Field.set must be the object, if it is an instance field, or null for static field. You are passing fieldName instead, which is obviously wrong.

So change

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

to

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

When your code doesn't have the necessary access rights, it may need to set the “accessible” state on the Field object. But generally, you should avoid repeating such expensive operations for every row of the ResultSet . So, you may use

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);
}

instead. Or even

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);
}

which is more complicated in the initialization, but reducing the repeated work inside the loop even further. Note that using Constructor here is more than an optimization, as starting with Java 9, Class.newInstance() has been marked deprecated .

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

 field.setAccessible(true);

Get familiar with FieldUtils package from apache commons, exactly with writeDeclaredField method:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM