Java JDBC类型转换(Firebird / Jaybird):在使用getter或updater ResultSet方法之前检查值/类型兼容性?

时间:2017-11-16 12:22:16

标签: java sql jdbc firebird jaybird

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

在实际使用结果集(例如运行updater方法)之前测试是否可以(并且是一种好的做法)是否可以将实际的Java Type /值安全地转换为目标SQL数据类型?

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

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

  • 我需要更新字段:ResultSet.updateBigDecimal(int columnIndex, BigDecimal x)。相应的更新程序是: x = new BigDecimal("123456789.1234")。如果我使用VARCHAR(5)(更高的精度和比例),我(逻辑上)会得到一个例外: 线程“main”中的异常org.firebirdsql.jdbc.field.TypeConversionException:转换为大小数时出错。
  • 我需要更新字段:ResultSet.updateString(int columnIndex, String x)。相应的更新程序为:x = "123456"。 如果我使用select ... into ...(更长的字符串6> 5),我(逻辑上)会得到一个异常:线程中的异常“main”java.sql.DataTruncation:数据截断。

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

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

我似乎很难找到我必须检查“按类型分类”的所有规则(即对于VARCHAR检查字符串长度,对于NUMERIC检查精度和比例等等 - 但还有什么?或者这是否足够?对于整数和浮点类型,无需检查任何内容?)。

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

1 个答案:

答案 0 :(得分:1)

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

通常情况下,您可以根据业务需求设计数据库并选择列类型,这自然会导致验证之前甚至尝试将其放入数据库中。

如果到目前为止还没有这样做,可以通过限制长度,使用Hibernate Validator等内容或验证UI框架,开始在输入表单中添加验证。

如果您正在处理高度动态的需求(例如用户提供的查询等),那么您应该使用JDBC提供的功能来创建自己的验证:预准备语句的ParameterMetaData和{{ 3}}结果集(也可以从准备好的语句中访问),特别是这些对象的getPrecision(和getScale),甚至可能是ResultSetMetaData之类的东西。

对于字符类型,getPrecision将指示最大字符数,对于numericdecimal类型,您可以使用之前的最大位数 >小数点为precision - scale

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

关于你的第二个问题,如果使用getter可能会导致转换异常:正常情况不会,但是例如在getInt()上调用BIGINT且值大于Integer.MAX_VALUE或{ {1}}会。