【问题标题】:How do I check to see if a column name exists in a CachedRowSet?如何检查 CachedRowSet 中是否存在列名?
【发布时间】:2010-10-02 12:42:11
【问题描述】:

我正在从可能发生变化的视图中查询数据。在执行crs.get******() 之前,我需要知道该列是否存在。

我发现我可以像这样查询 元数据 以查看在我从中请求数据之前是否存在列:

ResultSetMetaData meta = crs.getMetaData();
int numCol = meta.getColumnCount();

for (int i = 1; i < numCol + 1; i++) 
    if (meta.getColumnName(i).equals("name"))
        return true;

有没有更简单的方法来检查列是否存在?


编辑

它必须与数据库无关。这就是我引用CachedRowSet 而不是数据库的原因。

【问题讨论】:

    标签: java jdbc metadata cachedrowset


    【解决方案1】:

    对于通用 JDBC API,没有比这更简单的方法了(至少我不知道或找不到...我在自己开发的工具集中有完全相同的代码。)

    您的代码不完整:

    ResultSetMetaData meta = crs.getMetaData();
    int numCol = meta.getColumnCount();
    
    for (int i = 1; i < numCol + 1; i++) {
        if (meta.getColumnName(i).equals("name")) {
            return true;
        }
    }
    
    return false;
    

    话虽如此,如果您使用专有的、特定于数据库的 API 和/或 SQL 查询,我相信您可以找到更优雅的方式来做同样的事情。但是您必须为需要处理的每个数据库编写自定义代码。如果我是你,我会坚持使用 JDBC API。

    您提出的解决方案有什么地方让您认为它不正确吗?这对我来说似乎很简单。

    【讨论】:

    • 我是 cachedRowSet 的新手,我在写问题时才发现这一点。以连贯的方式提出问题让我以不同的方式思考。只要确保我走在正确的轨道上。
    • 如果你需要查找很多列,你总是可以让它返回一个由getColumnName(i) 方法调用填充的Set&lt;String&gt;。这样,您可以参考set.contains(myCol),而不是遍历所有内容。
    【解决方案2】:

    从 Jared 的这个线程中的最佳答案开始,以及 corsiKa 的一个被低估的 cmets :

    ResultSetMetaData meta = crs.getMetaData();
    int numCol = meta.getColumnCount();
    Set<String> columns = new HashSet<>;
    
    for (int i = 1; i <= numCol; i++) 
    {
        columns.add(meta.getColumnName(i));    
    }
    
    
    return columns.contains("name");
    

    【讨论】:

      【解决方案3】:

      旧线程,但我刚刚遇到了同样的问题并最终得到了一个实用函数:

      private Set<String> getColumnNames(ResultSet cached) throws SQLException {
          ResultSetMetaData metaData = cached.getMetaData();
          return IntStream.range(1, metaData.getColumnCount())
                          .mapToObj(i -> {
                              try {
                                  return metaData.getColumnName(i);
                              } catch (SQLException e) {
                                  throw new RuntimeException(e);
                              }
                          }).collect(toSet());
      }
      

      如果我们不必在 lambda 中捕获异常(没有一些丑陋的 hack),那就太优雅了

      【讨论】:

        【解决方案4】:

        如果列不在 CachedRowSet 中,您可以使用 findColumn() 将为 InvalidColumName 抛出 SQLException 的事实。

        例如

         try {
             int foundColIndex = results.findColumn("nameOfColumn");
        } catch {
          // do whatever else makes sense
        }
        

        可能滥用异常处理(根据 EffectiveJava 第 2 版第 57 条),但它是循环遍历元数据中所有列的替代方法。

        【讨论】:

          【解决方案5】:

          警告:以下评论纯粹来自记忆,没有任何支持性文书工作:)

          如果我没记错的话,当 oracle 缓存的行集实现与连接池一起使用时,会出现一个神秘的问题,这个问题非常难看。似乎有对缓存行集对象中保存的连接的静默引用(即使它应该断开连接),它关闭了随后从垃圾收集池中打开的另一个连接。出于这个原因,我最终放弃并编写了自己的数据对象层(这些天我将其交给 spring & hibernate)。

          【讨论】:

            【解决方案6】:

            不,真的没有更好的方法。你可能想重新审视这个问题。如果您可以重新定义问题,有时它会使解决方案变得更简单,因为问题已经发生了变化。

            【讨论】:

              【解决方案7】:

              哪个数据库?

              我认为在 Oracle 中有列出列的表。

              我不记得它是否也适用于视图,但我想它们确实有效,类似于:

              select colum_name from all_views where view_name like 'myview'
              

              或

              select name from all_objects where object_name like 'myview' and object_type='view'
              

              我不记得确切的语法。不过,您应该具有空间权限。

              每个 RDBMS 都应该有类似的东西。

              你也可以执行查询

              select * from myView where 1 = 0 ; 
              

              从元数据中获取列,如果您希望它避免获取数据之前知道列是否存在。

              【讨论】:

              • 它必须与数据库无关。我从未与 Oracle 合作过,但可能很快就会这样做。 +1 获取有关 Oracle 视图的一些有用信息。
              • 然后 select * from myview where 1 = 0 应该做的。虽然使用 RsMd,但速度非常快。
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2012-03-10
              • 2014-09-12
              • 1970-01-01
              • 2021-01-31
              • 1970-01-01
              相关资源
              最近更新 更多