【问题标题】:database access with JDBC and Java - without modelling tables and columns使用 JDBC 和 Java 访问数据库 - 无需建模表和列
【发布时间】:2021-03-06 10:29:31
【问题描述】:

我想通过 JDBC 读取和写入数据库表,而无需告诉我的 Java 代码关于表的任何信息,除了它们的名称。

我需要对数据进行的唯一处理是比较和读/写。详情见下文。

我实际上是在寻找类似的东西:

A = connect_db();
B = connect_db();
while (row = read_next_row(A)) {
    if (A.something == whatever) {
        insert_row(B, row);
    }
}

在 PHP 之类的东西中很容易,我将一行读入关联数组,完成。在 Java 中,这似乎过于复杂,但我不擅长 Java,所以我可能会错过一个明显、简单的解决方案。

这一切都适用于在多个数据库之间比较和复制数据的低级数据库优先工具。我可以假设这些表在 DB 之间是相同的,除了数据类型(一个 DB 可能称之为 String 和另一个 Varchar)和一些我可以安全忽略的源中的附加(内部计算)列。我正在寻找编码解决方案的原因是数据库系统不同(但都有 JDBC 连接器)。

但是,我的用户能够更改数据库结构,因此我的工具需要独立于列名和类型,除了一些列,如始终保证存在的主 ID。但是,例如,关于人员的表包含名字和姓氏(以及其他内容),我不能保证它将来不会包含中间名列。我希望不必为每个数据库结构更改更改非常简单的复制工具。

我错过了什么?这在 Java/JDBC 中可行吗?

【问题讨论】:

  • @Abra 我认为 ResultSetMetaData 可能是要走的路。但是,我不确定如何构建一个动态类型的列表、字典或数组来放入这些东西。没有做太多的 Java 开发。

标签: java jdbc


【解决方案1】:

查询时,您可以检查ResulSetMetaData 以发现查询的列名(或标签)。

PHP 关联数组的等价物是Map

一个你已经知道表名的简单例子:

public List<Map<String, Object>> getValues(String tableName, Connection connection) {
  try (var stmt = connection.createStatement();
       var rs = stmt.executeQuery("select * from " + stmt.enquoteIdentifier​(tableName, true))) {
    var result = new ArrayList<Map<String, Object>>();
    var rsmd = rs.getMetaData();
    int columnCount = rsmd.getColumnCount();
    while (rs.next()) {
      var row = new HashMap<String, Object>>(columnCount);
      for (int idx = 1; idx <= columnCount; idx++) {
        // or use getColumnLabel if you use a query that can have aliases
        row.put(rsmd.getColumnName(idx), rs.getObject(idx));
      }
      result.add(row);
    }
    return result;
  }
}

请注意,这会返回表的所有行,因此对于非常大的表,这在内存方面效率不高。因此,要处理大型表,您需要查看不同的解决方案,例如返回 Stream,或为行传递消费者(例如 Consumer&lt;Map&lt;String, Object&gt;&gt;)。

对于更高级的表单,您可以使用DatabaseMetaData.getTables 来发现可用的表,也可以选择使用DatabaseMetaData.getColumns 来发现表的列。

【讨论】:

  • 这非常有效。我想补充一点,您还可以通过访问 getColumnType 和 getColumnTypeName 来获取列 type
  • 看起来&gt;&gt;new HashMap&lt;String, Object&gt;&gt; 中的错字
猜你喜欢
  • 2015-06-10
  • 2016-06-18
  • 2015-02-02
  • 1970-01-01
  • 2014-02-03
  • 2013-07-14
  • 1970-01-01
  • 1970-01-01
  • 2018-06-17
相关资源
最近更新 更多