简体   繁体   中英

Set value in Setter according to number of column in ResultSetMetaData

I am looking for dynamic approach in order to set the values in setter method, in which I fetch the total number of column from ResultSetMetaData , on based of those result, I want to set the values in corresponding setter method. I already prepared the snippet in my utility class.

public Integer extractData(ResultSet rs) throws SQLException, DataAccessException {
    ResultSetMetaData rsmd = rs.getMetaData();
    int columnCount = rsmd.getColumnCount();
    for(int i = 1 ; i <= columnCount ; i++){
        SQLColumn column = new SQLColumn();
        String columnName = rsmd.getColumnName(i);
    }
    return columnCount;
}

Now the scenario is I want to set Pay_codes Of Employees, now there are total 95 paycode, but it differs in case of employees.

For example, Regular employees has 13 paycode, where as contactual employee has 6 codes, similarly society employees has 8 paycodes.

Now I need to show the list of paycodes on behalf of employee. I passed EmployeeCode and I got the result.

Now The problem
whether I set all the column in my RowMapper like below

Paycode pc=new PayCode();
if(rs.getString("ESIC") != null){  
    pc.setESICCode(rs.getString("ESIC"));
}
if(rs.getString("EPF") != null){  
    pc.setEPFCode(rs.getString("EPF"));
}
if(rs.getString("Allowance") != null){  
    pc.setAllowance(rs.getString("Allowance"));
}
and many more columns........till 300+ lines

This seems very bad approach, because, Paycode can be increase or decrease as per client request.

So, I am looking for 2-3 line of dynamic code which set the values in setter according to the column name inside "ResultSetMetaData".So Kindly suggest me the best approach and help me to achieve the same.

However I am thinking of generic implementation, is generic do some magic, If yes > then how? please suggest me.

Use this code:

private void mapFields(PayCode p, String setterName, Object value) {
    Method[] methods = PayCode.class.getDeclaredMethods();
    for(Method  method: methods){
        if(method.getName().contains(setterName)){
            try {
                method.invoke(p, value);
                break;
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }
    }
}

So you use Java reflection API with PayCode.class.getDeclaredMethods to get class methods, and then you iterate through method names searching for method that contains name of the property. Once you find it you set the value to the object with method.invoke(p, value) , and exit the loop.

You can make things faster if you store PayCode.class.getDeclaredMethods() , and then make a hash set with method name as a key, and method as a value Map<String, Method> :

static Map<String, Method> mapFields(Class clazz) {
    Method[] methods = clazz.getDeclaredMethods();
    Map<String, Method> result = new HashMap<>();
    for(Method  method: methods){
        String methodName = method.getName();
        if(methodName.indexOf("set") == 0){
            result.put(methodName.substring(3), method);
        }
    }

    return result;
}

and then use it:

Map<String, Method> fields = mapFields(PayCode.class);
if(fields.containsKey(name)){
    try {
        fields.get(name).invoke(p, value);
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    }
}
  1. You can use reflection

     package com.test; import java.lang.reflect.Method; class PayCode { private String esic; private String epf; public String getEsic() { return esic; } public void setEsic(String esic) { this.esic = esic; } public String getEpf() { return epf; } public void setEpf(String epf) { this.epf = epf; } @Override public String toString() { return "PayCode [esic=" + esic + ", epf=" + epf + "]"; } } public class DynamicSetter { public static void main(String[] args) { PayCode payCode = new PayCode(); try { /** * Here you can take "set" hardcoded and generate suffix "Esic" * dynamically, may be using apache StringUtils or implement using * Substring, based on your class setter methods. */ Method esicMethod = PayCode.class.getMethod("set" + "Esic", String.class); esicMethod.invoke(payCode, "Test Paycode"); System.out.println("Check paycode in object : " + payCode); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } } 
  2. You can use HashMap<> to add all pay code in that. You can also implement gtter for each pay code to read from HashMap.

     package com.test; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.util.HashMap; import java.util.Map; class Employee { private Map<String, String> payCodes = new HashMap<>(); private String epf; public String getEsic() { return payCodes.get("ESIC"); } public String getEpf() { return payCodes.get("EPF"); } public Map<String, String> getPayCodes() { return payCodes; } } public class DynamicSetter { public static void main(String[] args) { } public static Integer extractData(ResultSet rs) throws SQLException, DataAccessException { while(rs.next()) { Employee e = new Employee(); Map<String, String> payCodes = e.getPayCodes(); //set app paycode in payCodes, you can use column name as key and fetch value from result set. } } } 

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