Java select语句中的JDBC数字溢出

Java select语句中的JDBC数字溢出,java,jdbc,Java,Jdbc,我有一个java应用程序,它执行用户在UI上输入的SQL select语句。应用程序获取元数据以了解列类型: ResultSetMetaData metadata = rs.getMetaData(); int numColumns = metadata.getColumnCount(); for (int i=1;i<=numColumns;i++){ column[i] = metadata.getColumnType(i); } 一旦我得到结果集,对于每一行,我循环通过

我有一个java应用程序,它执行用户在UI上输入的SQL select语句。应用程序获取元数据以了解列类型:

ResultSetMetaData metadata = rs.getMetaData();
int numColumns = metadata.getColumnCount();
for (int i=1;i<=numColumns;i++){
    column[i] = metadata.getColumnType(i);  
}
一旦我得到结果集,对于每一行,我循环通过列来了解类型。根据类型,我使用getInt、getDate或getString获取值

问题是,在某些情况下,select有一个很大的和,当我执行getInt时,会出现一个数字溢出,我的例子中是从JDBC驱动程序Sybase得到一个错误。问题是getInt中要获得的数字大于int的容量

一种解决方案是使用getLong而不是getInt,但是由于我事先不知道用户输入的select列,所以我可能会对非常小的数值使用getLong,而在大容量中使用getLong,这将完全浪费64位字段


有没有办法解决这个问题?

在64位CPU的时代,也许getLong终究不会是一种浪费。但即使getLong也可能溢出,因此您更安全,但并非完全安全。BigDecimal让你处于安全的一边。由于您将应用程序描述为用户输入语句的UI,因此瓶颈很可能是用户本身或JDBC,而不是Java


您可以使用ResultSetMetaData.getColumnTypeint column确定列的类型,并根据该类型选择Java类型。您可以使用ResultSetMetaData.getColumnClassNameint列找出驱动程序建议的Java类,并使用ResultSet.GetObjective列检索数据。这是否真的方便还可能取决于驱动程序的质量。

我建议在这种情况下,当用户希望对数值列求和时,对int列始终使用下一个较大的数据类型long


原因是,您将花费至少那么多内存和处理,试图找出要使用的数据类型。您还可以保持代码简单,并升级到下一个更大的类型。

您可以为列执行乐观缓冲:首先为列数据使用int或更短的缓冲区,然后在try/catch中包装fetch循环以处理溢出异常。如果捕获到一个,请通过尝试将其检索为越来越宽的short->int->long->biginger/BigDecimal类型来检查缓冲区数据类型的宽度。然后通过分配一个更宽类型的新缓冲区并复制上一行的值来调整该列的缓冲区大小,然后重新开始检索


但这是相当复杂的代码。如果您能负担得起内存,那么最好使用long或biginger/BigDecimal。您应该检查一些示例数据集的实际大小和由此产生的内存节省。要知道,当您最终不得不加宽缓冲区时,缓冲区重新分配会有一点成本。如果结果集的大小实际上很容易在内存中为用户提供更简单的长检索或更广泛的检索,那么就没有问题,您也不必解决它。

您可以对任何已知的数字列使用BigDecimal…我不认为您真的渴望保存这些64位;也许问题是:如果对这些列使用long而不是int,你真的认为会有很大的性能损失吗?请保持简单。如果用户希望在数字列上求和,请始终使用下一个较大的数据类型long。