为什么我们在 NamedParameterJDBCTemplate 中获取 keyholder 值时添加 new String[]{"ID"}
Why do we add new String[]{"ID"} when fetching keyholder value in NamedParameterJDBCTemplate
为什么我们在 NamedParameterJDBCTemplate 中获取 keyholder 值时添加 new String[]{"ID"}
?
我的问题是基于这个问题的答案:
Is there a way to extract primary key(or ROWID) using NamedParameterJdbcTemplate and GeneratedKeyHolder?
我的问题听起来可能很愚蠢,但我确实需要对此进行澄清。
我知道,尝试使用 Keyholder 从 DB 获取 PK 时出现异常的解决方案:生成的密钥不是受支持的数字类型。无法将 [oracle.sql.ROWID] 转换为 [java.lang.Number]
我的问题是,为什么我们将 ID 转换为字符串数组,然后获取它的 long 值?不能直接取long值吗?
代码片段参考上面的答案link。我的问题是基于答案。
默认情况下,Spring的JdbcTemplate会使用JDBC的Statement.RETURN_GENERATED_KEYS
选项。问题是 Oracle JDBC 驱动程序不会 return 该选项的 id 列的值,而是 return 一个 'row id' (基本上是一个指向该行的内部指针,而不是该行中的 id 值)。对于大多数用例,这不是 suitable,因为它需要您使用行 id 显式查询行以获取实际的 id 值,具体在 Spring 的 KeyHolder 的实现中它导致上述错误,因为 java.sql.RowId
实现不是很长(也不是 java.lang.Number
的子类)。
幸运的是,JDBC 提供了额外的方法来获取生成的列:通过显式指定您想要的列的列名(或列索引)。这就是 new String[] {"ID"}
所做的。它指示 JdbcTemplate 将这个列名数组传递给 JDBC 驱动程序,并且驱动程序 - 假设它支持此功能 - 将 return 指定的列,也就是说,如果你的 table 实际上有一个名称为 ID
.
的列
换句话说,这不会"将 ID 转换为字符串数组然后获取其长值",它会检索列 ID
的值而不是 Oracle JDBC 驱动程序 return 插入行的 'row id'。
您 link 的问题专门针对 Oracle(默认为 return 行 ID)。 Oracle JDBC 驱动程序 return 的行 ID 的原因是因为直到最近 Oracle 还没有标识列,并且具有类似标识行为的唯一方法是使用自定义触发器来生成 ID。这使得无法确定 table 是否生成了列,如果是,是哪一列。相反,实施决定是 return 行 ID,除非指定了明确的列。
虽然这个问题是 Oracle 特有的,但其他驱动程序可能有不同的问题,可能需要使用相同的解决方案来解决:例如一些驱动程序(例如 PostgreSQL 和 Firebird(Jaybird,Firebird JDBC 驱动程序我维护)) 将默认为 returning 所有列,如果您的 ID 列不是第一列,这可能会导致类似的错误,因为 Spring GeneratedKeyHolder.getKey()
方法假定生成的 id保存在生成的键结果集的第一列中。
为什么我们在 NamedParameterJDBCTemplate 中获取 keyholder 值时添加 new String[]{"ID"}
?
我的问题是基于这个问题的答案: Is there a way to extract primary key(or ROWID) using NamedParameterJdbcTemplate and GeneratedKeyHolder?
我的问题听起来可能很愚蠢,但我确实需要对此进行澄清。 我知道,尝试使用 Keyholder 从 DB 获取 PK 时出现异常的解决方案:生成的密钥不是受支持的数字类型。无法将 [oracle.sql.ROWID] 转换为 [java.lang.Number]
我的问题是,为什么我们将 ID 转换为字符串数组,然后获取它的 long 值?不能直接取long值吗?
代码片段参考上面的答案link。我的问题是基于答案。
默认情况下,Spring的JdbcTemplate会使用JDBC的Statement.RETURN_GENERATED_KEYS
选项。问题是 Oracle JDBC 驱动程序不会 return 该选项的 id 列的值,而是 return 一个 'row id' (基本上是一个指向该行的内部指针,而不是该行中的 id 值)。对于大多数用例,这不是 suitable,因为它需要您使用行 id 显式查询行以获取实际的 id 值,具体在 Spring 的 KeyHolder 的实现中它导致上述错误,因为 java.sql.RowId
实现不是很长(也不是 java.lang.Number
的子类)。
幸运的是,JDBC 提供了额外的方法来获取生成的列:通过显式指定您想要的列的列名(或列索引)。这就是 new String[] {"ID"}
所做的。它指示 JdbcTemplate 将这个列名数组传递给 JDBC 驱动程序,并且驱动程序 - 假设它支持此功能 - 将 return 指定的列,也就是说,如果你的 table 实际上有一个名称为 ID
.
换句话说,这不会"将 ID 转换为字符串数组然后获取其长值",它会检索列 ID
的值而不是 Oracle JDBC 驱动程序 return 插入行的 'row id'。
您 link 的问题专门针对 Oracle(默认为 return 行 ID)。 Oracle JDBC 驱动程序 return 的行 ID 的原因是因为直到最近 Oracle 还没有标识列,并且具有类似标识行为的唯一方法是使用自定义触发器来生成 ID。这使得无法确定 table 是否生成了列,如果是,是哪一列。相反,实施决定是 return 行 ID,除非指定了明确的列。
虽然这个问题是 Oracle 特有的,但其他驱动程序可能有不同的问题,可能需要使用相同的解决方案来解决:例如一些驱动程序(例如 PostgreSQL 和 Firebird(Jaybird,Firebird JDBC 驱动程序我维护)) 将默认为 returning 所有列,如果您的 ID 列不是第一列,这可能会导致类似的错误,因为 Spring GeneratedKeyHolder.getKey()
方法假定生成的 id保存在生成的键结果集的第一列中。