当前位置: 首页 > 知识库问答 >
问题:

如果使用java Reflection列名称和字段名称不同,如何使用数据库ResultSet映射POJO?

严扬
2023-03-14

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

例如:如果我的列名是order_ID,而在我的pojo中它是orderId,则order_ID不会与order ID映射。下面是我使用的逻辑。请提出解决方案或想法。提前谢谢!

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

共有2个答案

西门良才
2023-03-14

我最近也做了类似的事情,虽然很粗糙,但很有效。

// 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("列名")将任何数据类型检索为String。Oracle文档说

请注意,虽然建议使用getString方法来检索SQL类型CHAR和VARCHAR,但可以使用它检索任何基本的SQL类型。使用getString获取所有值可能非常有用,但它也有其局限性。例如,如果它用于检索数值类型,getString会将数值转换为JavaString对象,并且必须将值转换回数值类型,然后才能将其作为数字进行操作。无论如何,如果将值视为字符串,则没有缺点。此外,如果希望应用程序检索SQL3类型以外的任何标准SQL类型的值,请使用getString方法

冉永宁
2023-03-14

但是,如果列名与pojo中的字段不同,则不会对其进行映射

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

我能想到的唯一解决方法是将字段名映射到DB列名的二级全局映射,然后您可以引用它一次columnNames。containsKey(fieldName)为false。该映射是一个手动工作,并且手动工作将始终存在,因为只有作为开发人员的您才知道哪些列映射到POJO中的哪个字段。如果两者不同,就无法实现自动化

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

有ApacheCommons dbutils之类的API,但手动映射也不会消失,因为您必须在自定义组织中提供。阿帕奇。平民德布提尔斯。豆处理器

还可以做其他事情,比如JPA实体生成工具行,我们将下面的内容附加到POJO字段-

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

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

如何使用反射获取注释类名、属性值

 类似资料:
  • 问题内容: Jackson json注释中以下jax-b注释的等效方式是什么? 我需要生成json而不是xml,并且需要了解在jax-b中等效表示的常规jackson批注。 重命名字段。 使用getter代替字段。 如果json / xml元素名称是Java保留字(例如“ ”,“ ”,“ ”等),则这些功能尤其重要。 因此我们必须将POJO字段分别命名为“ new ”,“ _ public ”,“

  • 我使用jooq针对本地数据库生成对象,但在以后的生产中运行“for real”时,实际数据库将具有不同的名称。为了解决这个问题,我使用

  • 如果所有的命名都是按照 Mapper 的映射来操作的,那当然是最理想的。但是如果碰到某个表名或者某个字段名跟映射规则不匹配时,我们就需要别的机制来改变。xorm 提供了如下几种方式来进行: 如果结构体拥有 TableName() string 的成员方法,那么此方法的返回值即是该结构体对应的数据库表名。 通过 engine.Table() 方法可以改变 struct 对应的数据库表的名称,通过 s

  • 我有一个Java程序,我可以把它变成一个安装程序exe,使一个应用程序exe 我希望安装程序exe看起来像,而实际的应用程序看起来像jpackage,我看不到这样做的方法,也看不到其他人这样做的例子。目前,我的安装程序和我的应用程序具有相同的名称。 我不想要jpackage的替代品,我知道还有其他方法,我只是在寻找用jpackage做这件事的方法。

  • 问题内容: 例如,mysql引用表名使用 注意` 其他数据库是否曾经使用过不同的char来引用其表名 问题答案: 引号的这种使用称为定界标识符。这是SQL的重要组成部分,因为否则您将不能使用以下标识符(例如表名和列名): 包含空格:“我的桌子” 包括特殊字符和标点符号:“我的表格” 包括国际字符:“私のテーブル” 区分大小写:“ MyTable” 匹配SQL关键字:“表” 标准SQL语言对定界标识

  • 问题内容: 我需要获取SQL Server中的所有表名。为此,我使用以下代码: 我需要使用动态数据库名称。为此,我尝试使用以下代码: 但这是行不通的。我怎样才能做到这一点 ? 问题答案: 或简单地: