0

如果我理解(并测试示例 JDBC 代码;使用 Jaybird for Firebird)很好,即使使用正确的(= 尊重类型映射)更新程序方法(例如ResultSet.updateString)或PreparedStatement参数,也会带来“转换异常”。

在实际使用结果集(例如运行更新程序方法)之前测试实际的 Java 类型/值是否可以安全地转换为目标 SQL 数据类型,是否有可能(并且这是一个好习惯)?

“问题”只是一种方式吗?即从SQL 转换回Java 时(使用getter 方法),是否保证正确的getter 方法永远不会失败(由于转换问题)?

我的示例(使用 Jaybird 3.0.2、JDK1.8):

  • 我需要更新字段:NUMERIC(9,2). 对应的更新器是: ResultSet.updateBigDecimal(int columnIndex, BigDecimal x). 如果我使用x = new BigDecimal("123456789.1234")(更大的精度和规模),我(逻辑上)得到一个异常: 线程“主”org.firebirdsql.jdbc.field.TypeConversionException 中的异常:转换为大十进制时出错。
  • 我需要更新字段:VARCHAR(5). 对应的更新器是:ResultSet.updateString(int columnIndex, String x). 如果我使用x = "123456"(更长的字符串 6 > 5),我(逻辑上)得到一个异常:线程“main”java.sql.DataTruncation 中的异常:数据截断。

除了尝试运行查询和捕获异常之外,是否有一些通用的优雅方式(不取决于特定类型)如何检查实际的 Java 值/对象是否可以“保存”到某些 SQL 字段?

我想检查我的数据编辑对话框中已经存在的值(在实际运行更新查询之前)。简单的测试“VALUE OK / NOT OK”就可以了(只知道目标 SQL 类型)。

对我来说似乎很难找到我必须检查“按类型”检查的所有规则(即对于 VARCHAR 检查字符串长度,对于 NUMERIC 检查精度和比例等 - 但还有什么?或者这就足够了?对于整数和浮动类型不需要检查任何东西?)。

我试图浏览 Jaybird 源代码,但“转换过程”非常复杂(并且特定于类型),我自己找不到答案。

4

1 回答 1

1

在您实际设置值之前,JDBC 不提供任何“检查”值,因此 Jaybird 也不提供:设置值就是检查。确切的行为取决于驱动程序,Jaybird 尝试验证设置值,但其他驱动程序可能会选择将其推迟到数据库本身(因此错误只会在执行时发生)。

通常,您会根据业务需求设计数据库并选择列类型,这自然会在您尝试将其放入数据库之前进行验证。

如果您直到现在还没有这样做,请开始向您的输入表单添加验证,通过限制长度、使用 Hibernate Validator 之类的东西或验证您的 UI 框架。

如果您正在处理高度动态的需求(例如用户提供的查询等),那么您应该使用 JDBC 确实提供的功能来创建您自己的验证:ParameterMetaData准备好的语句和ResultSetMetaData结果集的声明),特别是这些对象的getPrecision(和getScale),甚至可能是DatabaseMetadata.getColumns.

对于字符类型,getPrecision将指示最大字符数,对于 anumericdecimal类型,您可以使用小数点precision - scale的最大位数作为.

但是在 Jaybird 中,这不是 100% 精确的,例如,如果 Jaybird 无法识别底层列,getPrecision可能会返回 9 ,并且 Jaybird(和 Firebird)实际上允许精度为 10,但有一些限制(即未缩放的最大值numeric(8,2)的值Integer.MAX_VALUE,即这种类型的 21474836.47)。

至于你的第二个问题,如果使用 getter 会导致转换异常:正常情况下不会,但例如调用getInt()aBIGINT的值大于Integer.MAX_VALUEInteger.MIN_VALUE会。

于 2017-11-16T19:29:42.720 回答