2

I am working in dynamically mapping the values from Result Set to POJO using Java reflection. It is working, but if the column name is different from the field in pojo it is not getting mapped.

For ex: if my column name is ORD_ID and in my pojo it is orderId, the ord_id is not getting mapped with order id. Here is the logic i'm using below.Kindly suggest a solution or an idea. Thanks in advance !

    int colCount = resultSet.getMetaData().getColumnCount();
    for (int i = 0; i < colCount; i++) 
    {
    columnNames.put(resultSet.getMetaData().getColumnName(i + 1).toLowerCase(), i);
    }
    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.setAccessible(true); 
                field.set(newObj, resultSet.getObject(index+1));
            }
        }
        results.add(newObj);
    }
Pradeep Anand
  • 145
  • 3
  • 14

2 Answers2

2

but if the column name is different from the field in pojo it is not getting mapped

Obviously, that wouldn't work since your code is written for that very purpose when both names match so I don't understand the surprise element.

Only way out that I can think of is a secondary global map of field name to DB Column name and you refer to it once columnNames.containsKey(fieldName) is false. That map is a manual work and that manual work will always be there since only you as a developer know that which column maps to which field in the POJO. That can't be automated if both are different & external mapping needs to be fed to Java progarm.

That mapping can be kept in an external property file.

There are APIs like apache-commons-dbutils but again manual mapping wouldn't go away as you will have to provide that in your custom - org.apache.commons.dbutils.BeanProcessor

Something else can be done the lines of JPA entity generation tools where we attach something like below to POJO fields -

@Column(name = "ADDRESS_IND")
private String addressInd;

but that is again a manual work as far as mapping specification is concerned. I think, you can retrieve annotation value and construct your mapping.

How to get annotation class name, attribute values using reflection

Sabir Khan
  • 9,826
  • 7
  • 45
  • 98
0

I did something similar recently, it's very crude but it works.

// finalData format will be [List<String>,List<List<String>>] i.e [column names, column data]
    List<Object> finalData = new ArrayList<Object>();
    List<String> columnNames = new ArrayList<>();
    // columnData will be list of lists, where inner list comprised of each row data and outer list comprised of such row objects.
    List<List<String>> columnData = new ArrayList<List<String>>();


    ResultSet rs = serviceDao.generateData(query);//returns result set based on query

    ResultSetMetaData rsmd = rs.getMetaData();
    int columnCount = rsmd.getColumnCount();
    for (int i = 1; i <= columnCount; i++ ) {
      String columnName = rsmd.getColumnName(i);
      columnNames.add(columnName);
    }

    finalData.add(columnNames);// first object of finalData object
    //Iterate through result set for each row, get all the columns data which are present in column names
    while(rs.next()) {
        List<String> rowData = new ArrayList<String>();
        for(int i=0;i<columnNames.size();i++) {
            rowData.add(rs.getString(columnNames.get(i)));
        }
        columnData.add(rowData);
    }
    finalData.add(columnData); // Second object of finalData object

Edit 1: you can use rs.getString("column name") to retrieve any datatype as Strings. Oracle docs says

Note that although the method getString is recommended for retrieving the SQL types CHAR and VARCHAR, it is possible to retrieve any of the basic SQL types with it. Getting all values with getString can be very useful, but it also has its limitations. For instance, if it is used to retrieve a numeric type, getString converts the numeric value to a Java String object, and the value has to be converted back to a numeric type before it can be operated on as a number. In cases where the value is treated as a string anyway, there is no drawback. Furthermore, if you want an application to retrieve values of any standard SQL type other than SQL3 types, use the getString method.

raviraja
  • 676
  • 10
  • 27