如果 columnNames 和 fieldNames 使用 java 反射不同,如何将 POJO 与数据库 ResultSet 映射?

How to map the POJO with the database ResultSet if the columnNames and fieldNames is different using java Reflection?

我正在使用 Java 反射将值从结果集动态映射到 POJO。它正在工作,但如果列名与 pojo 中的字段不同,则它不会被映射。

例如:如果我的列名称是 ORD_ID 并且在我的 pojo 中它是 orderId,则 ord_id 不会与订单 ID 映射。这是我使用的逻辑 below.Kindly 建议解决方案或想法。提前致谢!

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

我最近做了类似的事情,很粗糙但是很管用。

// 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

编辑 1: 您可以使用 rs.getString("column name") 将任何数据类型检索为字符串。 Oracle docs

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.

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

显然,这行不通,因为当两个名称匹配时,您的代码就是为此目的而编写的,所以我不理解 surprise 元素。

我能想到的唯一出路是字段名称到数据库列名称的辅助全局映射,一旦 columnNames.containsKey(fieldName) 为假,您就可以参考它。该映射是一项手动工作,并且该手动工作将始终存在,因为只有您作为开发人员知道哪个列映射到 POJO 中的哪个字段。如果两者不同并且需要将外部映射提供给 Java progarm,则无法实现自动化。

该映射可以保存在外部 属性 文件中。

有像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

这样的API

可以在 JPA 实体生成工具行中完成其他操作,我们将如下所示的内容附加到 POJO 字段 -

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

但就映射规范而言,这又是一项手动工作。我认为,您可以检索注释值并构建您的映射。

How to get annotation class name, attribute values using reflection