【问题标题】:ResultSet "column not found" with c3p0使用 c3p0 的结果集“未找到列”
【发布时间】:2013-06-16 07:33:57
【问题描述】:

我有一个对数据库的查询,结果是通过java.sql.ResultSet获得的,因为这个查询是动态的,返回的列数可能是 5 或 7,过去使用相同的代码生成一个“未找到列异常”并包含在以下捕获中:

try{
    sTemp = this.rsResults.getString("col3");
   }catch(Exception e){}

但是现在使用相同的 try 和 catch(唯一的区别是现在我使用 combopooldatasource 和它们的连接),我得到了两个不属于 catch 的异常。

我该如何改进这一点,有没有更好的方法来检查列是否存在? c3p0 是否必须基于(SQLState: S0022) column not found error 强制测试连接?

Error n1 - in the com.mchange.v2.c3p0.impl.NewProxyResultSet.getString qlUtils.toSQLException() - Attempted to convert SQLException to SQLException. Leaving it alone. [SQLState: S0022; errorCode: 0]
java.sql.SQLException: Column 'col3' not found.

Error n2 -  DefaultConnectionTester.statusOnException() - Testing a Connection in response to an Exception:
java.sql.SQLException: Column 'col3' not found.

ps:使用的驱动是一样的org.gjt.mm.mysql.Driver

【问题讨论】:

    标签: java mysql c3p0


    【解决方案1】:

    在我的特殊情况下,我进行了以下(粗略的)测试,只是为了说明引发异常与检查 RecordSet 中是否存在列的成本。

    要检查的列数是 169。

    代码 1

    try
    {
     sTemp = this.rsResults.getString("col3");
    }catch(Exception e){}
    try
    {
     sTemp = this.rsResults.getString("col4");
    }catch(Exception e){}
    
    ...
    
    try
    {
     sTemp = this.rsResults.getString("col169");
    }catch(Exception e){}
    

    带有函数hasColumn的代码2 [问题]:How can I determine if the column name exist in the ResultSet?

    ResultSetMetaData rsmd = null;
    try {
         rsmd = this.rsResults.getMetaData();
    } catch (SQLException e1) {
     e1.printStackTrace();
    }
    
    try{
     if (rsmd != null && hasColumn(rsmd,"col3"))
      sTemp = this.rsResults.getString("col3");
    }catch(Exception e){}
    
    try{
     if (rsmd != null && hasColumn(rsmd,"col4"))
      sTemp = this.rsResults.getString("col4");
    }catch(Exception e){}
    
    ...
    
    try{
     if (rsmd != null && hasColumn(rsmd,"col169"))
      sTemp = this.rsResults.getString("col169");
    }catch(Exception e){}
    

    没有 c3p0 的结果

               code 1   code 2
    query nº1   75ms     36ms
    query nº2   40ms     43ms
    query nº3   227ms    46ms
    query nº4   262ms    18ms
    

    在 INFO 处使用 c3p0 日志级别的结果

               code 1   code 2
    query nº1   519ms     45ms
    query nº2   358ms     28ms
    query nº3   2348ms    9ms
    query nº4   3243ms    12ms
    

    作为结论,在这两种情况下,特别是在使用 c3p0 时,仅检查列是否存在(除了不好的做法之外)引发异常的成本很高。

    【讨论】:

      【解决方案2】:

      c3p0 在内部对任何类型的异常进行连接测试,但来自该测试的异常不会被抛出或对客户端代码可见。您之所以看到它,是因为您在 DEBUG 级别记录 c3p0 输出。 c3p0 的东西应该记录在 INFO 以供正常使用。如果您以 DEBUG-ish 级别登录,您会看到各种警告消息和堆栈跟踪。

      【讨论】:

      • 是的,这是真的,但是如果我将日志记录设置为 INFO,连接测试还会发生吗?如果是,那么提高测试的成本加上异常堆栈的成本仍然很高,这就是我想要避免的
      • 是的,测试仍然会进行。 c3p0 假定 Exceptions 表示异常情况,并且总是在 Exceptions 之后进行测试以确定 Connection 是否适合在池中重用,或者是否应在关闭时标记为销毁。如果您设置了 preferredTestQuery 或 automaticTestTable 属性,则连接测试的成本不会很高。然而,默认测试通常很慢。
      • 好的,谢谢史蒂夫。我认为异常(col not found)的成本是最困扰我的,我正在使用原始代码(try&catch with SQLException column not found)和修改后的代码(检查列之前是否存在 ResultSet.getString ()) 所有有和没有 c3p0,完成后我会在这里发布结果。
      【解决方案3】:

      检查ResultSetMetaData

      ResultSet rs = stmt.executeQuery("SELECT * FROM your_table");
      
      ResultSetMetaData rsmd = rs.getMetaData();
      int numberOfColumns = rsmd.getColumnCount();
      
      // test the number of columns returned
      if (numberOfColumns == 5) {
          //
      } else {
          // numberOfColumns = 7
      }
      
      // or, test the column names
      if ("col3".equals(rsmd.getColumnName(3)) {
          // col3 exists
      }
      

      编辑:
      如果您不想修改您的源代码,而只是希望您当前的方法也可以使用c3p0;只需捕获 Throwable(虽然它确实让我不寒而栗:)

      try {
          sTemp = this.rsResults.getString("col3");
      } catch (Throwable t) {
          // Both, Exceptions and Errors are ignored now
      }
      

      【讨论】:

      • 感谢您的回复,ResultSetMetaData 如果可以检查 col3 是否存在,但 col3 会更改它在 select 语句中的位置。 ResultSet 的 getString 方法非常完美,因为如果列不存在会返回 docs.oracle.com/javase/6/docs/api/java/sql/… 中描述的异常,我的问题是使用 c3p0 时出现这个特殊异常。
      • 我不喜欢 Throwable,因为我不想记录任何内容,也不想处理除了未找到的列之外可能出现的任何错误和异常。我会修改源代码,这是最好的方式。
      猜你喜欢
      • 2020-07-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-30
      • 2014-11-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多