Pradeep Anand
Pradeep Anand

Reputation: 155

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

Upvotes: 0

Views: 2003

Answers (3)

Holger
Holger

Reputation: 298529

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.

Upvotes: 1

Kamil W
Kamil W

Reputation: 2376

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

Upvotes: 0

Vasif
Vasif

Reputation: 798

Can you try below line before setting value?

 field.setAccessible(true);

Upvotes: 0

Related Questions