【问题标题】:Is there any drawback of using long instead of int when preparing a statement in java?在 java 中准备语句时使用 long 而不是 int 有什么缺点吗?
【发布时间】:2018-06-26 08:55:03
【问题描述】:
如果我将PreparedStatement.setLong 用于对应db 列实际上是MySql integer 的参数,传递int 显然会在java 中看到它自动加宽。但是在 jdbc 的“较低”级别中,这有什么关系吗?如果我预计 db 列的数据类型在不久的将来会更改为 biginteger,那么使用 long 可以避免额外的工作吗?
编辑:我的意思是设置long 的方法总是收到int,所以我不会意外传递一个对于db 列来说太大的值。
【问题讨论】:
标签:
java
mysql
jdbc
prepared-statement
primitive
【解决方案1】:
从 100% 正式的角度来看,将 setLong 用于 INTEGER 列可能是不安全的。 JDBC 4.3 规范说setXXX-方法(setObject 除外)遵循附录 B.2 的映射,即 Java long 映射到 SQL BIGINT。然后取决于驱动程序或数据库是否可以使用带有INTEGER 列的BIGINT 值。
关于这个问题的 JDBC 1.20 规范说:
7.2.1 IN 参数的数据类型一致性
PreparedStatement.setXXX 方法不执行任何一般数据
类型转换。相反,Java 值只是简单地映射到
对应的 SQL 类型(遵循表 3 中指定的映射)
第 28 页)并将该值发送到数据库。
程序员有责任确保 java 类型
每个参数映射到与 SQL 兼容的 SQL 类型
数据库期望的数据类型。为了最大的便携性
程序员,应该使用与确切 SQL 对应的 Java 类型
数据库期望的类型。
如果程序员需要对 IN 参数进行数据类型转换,他们
可以使用 PreparedStatement.setObject 方法来转换 Java
对象到指定的 SQL 类型,然后将值发送到
数据库。
最近的 JDBC 规范中不再存在此措辞,但其意图仍然适用,并由 JDBC 4.3 中的附录 B.2 定义。
然而,实际上,许多 JDBC 驱动程序(包括 MySQL 连接器/J)支持更广泛的转换,类似于附录 B.5 中为 setObject 定义的转换,尽管每个驱动程序都有其注意事项和怪癖这里。对于Long,这意味着getObject 可以定位TINYINT、SMALLINT、INTEGER、BIGINT、REAL、FLOAT、DOUBLE、DECIMAL、DECIMAL、DOUBLE、DECIMAL、@986 、BOOLEAN、CHAR、VARCHAR、LONGVARCHAR,这通常意味着您也可以对 setLong 执行相同的操作。
这也为附录 B.6 中定义的 getLong 的转换提供了统一性。
它是否有任何缺点,取决于实现。 MySQL Connector/J 驱动程序是开源的,因此如果您想了解详细信息:请查看源代码。
但是,如果您的应用程序实际上使用long,为什么数据库类型是INTEGER?在您的数据库中使用BIGINT 来匹配您的应用程序,或者在您的应用程序中使用int 来匹配数据库。