【问题标题】:Any better approach rather than result.getString() while iterating a result set in java在 java 中迭代结果集时,任何比 result.getString() 更好的方法
【发布时间】:2012-03-30 11:13:46
【问题描述】:

我在一个表中有 6 列。我有一个选择查询,它从表中选择一些记录。在遍历结果集时,我使用以下逻辑来提取列中的值:

Statement select = conn.createStatement();
        ResultSet result = select.executeQuery
        ("SELECT * FROM D724933.ECOCHECKS WHERE ECO = '"+localeco+"' AND CHK_TOOL = '"+checknames[i]+"'");
         while(result.next()) { // process results one row at a time
           String eco = result.getString(1);
           mapp2.put("ECO", eco);
           String chktool = result.getString(2);
           mapp2.put("CHECK_TOOL", chktool);
           String lastchktime = result.getString(3);
           mapp2.put("LAST_CHECK_TIME", lastchktime);
           String status = result.getString(4);
           mapp2.put("STATUS", status);
           String statcmts = result.getString(5);
           mapp2.put("STATUS_COMMENTS", statcmts);
           String details = result.getString(6);
           mapp2.put("DETAILS_FILE", details);
         }            

我有两个问题: 1.有没有比使用result.getString()更好的方法??? 2. 可以说,稍后会向表中添加另一列。我的代码有什么方法可以在不更改代码的情况下处理这个新增内容

【问题讨论】:

    标签: java jdbc resultset


    【解决方案1】:

    您可以使用ResultSetMetaData 来确定您的ResultSet 中的列的数量和名称,并以这种方式处理。但请注意,更改数据库中的列数 - 影响您的代码 - 并让代码仍然工作可能并不总是一个好主意。

    另外,请注意,您在循环的每次迭代中都会覆盖地图中的值。您可能想将这些地图添加到某种列表中?

    最后,您需要确保您的getString 方法不会在任何地方返回null,否则将其放入地图会引发异常。

    Statement select = conn.createStatement();
    ResultSet result = select.executeQuery("SELECT * FROM D724933.ECOCHECKS WHERE ECO = '"+localeco+"' AND CHK_TOOL = '"+checknames[i]+"'");
    ResultSetMetaData rsmd = result.getMetaData();
    
    int numberOfColumns = rsmd.getColumnCount();    
    List data = new ArrayList<Map>();
    Map mapp2;
    
    while(result.next()) { // process results one row at a time
        mapp2 = new HashMap<String, String>();
        for(int i=1; i<=numberOfColumns; i++) {
            mapp2.put(rsmd.getColumnName(i), rs.getString(i));
        }
        data.add(mapp2);
    }
    

    【讨论】:

    • @jtahlborn 因为我要检索所有列并且按索引检索比按名称检索要快。如果您愿意,可以使用rs.getString(rsmd.getColumnName(i)) - 但为什么呢?记住,列名事先是不可用的,我需要在运行时获取它们。
    • Aleks G 对整个答案非常正确。在他的回答中,我看不出有什么可否决的。我接受他的回答作为我问题的正确解决方案
    【解决方案2】:

    ResultSet 上的每个 get 系列方法都有一个以列名作为参数的重载变体。您可以改用它来减少对列排序的依赖。

    ResultSet results = ...;
    results.getString(1);
    

    你可以这样做:

    results.getString("name");
    

    但处理此类问题的首选方法是通过显式在初始查询中选择您想要的列,对结果集施加您自己的排序。

    【讨论】:

      【解决方案3】:

      如果您的表添加了一个新列,那么显然您必须更改您的代码,因为在您的代码中您使用硬编码值,我的意思是 getString(1)。

      改为使用 ResultSetMetaData 的 getColumnCount 并执行一些其他逻辑来动态获取那么多列值。

      关于第一个问题的另一件事,ResultSet 包含具有两种类型参数的 getXXX() 方法,String column name int 列索引。您使用 index 而不是 column name,它的执行速度会稍微快一些。

      【讨论】:

        【解决方案4】:

        使用SELECT * 是不好的做法,您应该只选择您感兴趣的列。原因正是您提到的:如果您的数据库发生变化会发生什么。您不想浏览整个代码并查找和编辑所有 SELECT * 语句。

        您不需要将结果放入您自己的地图中,因为您已经可以这样做了:

        result.getString("DETAILS_FILE");
        

        但已经有其他答案解释了这一点。

        使用常量代替字符串“DETAILS_FILE”会更有帮助。您可以在SELECTresult.getString() 中使用常量。如果您的数据库发生变化,您只需引入新常量或更改现有常量。

        【讨论】:

        • 同意你关于 SELECT * 的使用。我将其更改为我需要的列名
        • 虽然我同意使用 SELECT *,但有正当理由可能需要这样做。还有一些原因可能需要从数据库中读取数据并将其放入您自己的地图中 - 例如,因为您随后将此地图传递到应用程序的另一层,其中数据库层不可用。总体而言,您的答案虽然本身是正确的,但并不能回答 OP 提出的问题。
        猜你喜欢
        • 2013-02-27
        • 2013-12-21
        • 1970-01-01
        • 1970-01-01
        • 2016-07-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-01-17
        相关资源
        最近更新 更多