RETURN_GENERATED_KEYS 和指定生成的列名之间的区别

Posted

技术标签:

【中文标题】RETURN_GENERATED_KEYS 和指定生成的列名之间的区别【英文标题】:Difference between RETURN_GENERATED_KEYS and specifying the generated column names 【发布时间】:2015-08-13 15:52:13 【问题描述】:

JDBC Connection 类的prepareStatement(String sql, int autoGeneratedKeys)prepareStatement(String sql, String[] columnNames) 方法有什么区别?

两者的 Javadoc 表明,如果 SQL 语句是 INSERT 语句,则返回的 PreparedStatement 对象能够返回自动生成的键。对于第一个 API,需要为 autoGeneratedKeys 参数传递 Statement.RETURN_GENERATED_KEYS。在第二个 API 的情况下,生成的列的名称作为字符串数组传递。

使用其中一种的原因是什么?

我注意到 Spring 的 SimpleJdbcInsert 类更喜欢指定列名的变体:AbstractJdbcInsert.prepareStatementForGeneratedKeys

为什么会这样?

【问题讨论】:

【参考方案1】:

原因是方便、灵活、性能和兼容性。例如,某些数据库无法知道哪些列是自动生成的,因此默认情况下,它们的驱动程序在使用Statement.RETURN_GENERATED_KEYS 时会返回all 列。

这可能会影响性能,因为:

    所有这些值都需要从数据库传输到客户端, 在某些数据库中,这需要对元数据进行查询才能知道要获取哪些列。

例如,PostgreSQL 的驱动程序将附加RETURNING *(因此它只需要担心第 1 点),而 Firebird 驱动程序(我维护的)也必须查询元数据。

一些数据库驱动默认返回一个不直接有用的列(例如Oracle - 曾经? - 返回ROWID,这意味着你必须自己查询实际的字段),一些数据库只返回主键,而可能还有其他生成的字段,我相信一些数据库驱动程序会返回最后生成的键,即使表不使用标识字段(!)。

prepareStatement(String sql, String[] columnNames)prepareStatement(String sql, int[] columnIndexes) 方法对返回的内容提供了更多控制(如果支持)。如果您确切知道需要或想要哪些字段,则可以指定它们并准确获取这些字段,而不必担心使用 RETURN_GENERATED_KEYS 时所获得的行为差异。

根据实现的不同,采用String[] columnNames 的方法可能最有效,因为名称可以简单地逐字输入,而int[] columnIndexes 可能仍需要元数据查询才能获取实际名称。

【讨论】:

以上是关于RETURN_GENERATED_KEYS 和指定生成的列名之间的区别的主要内容,如果未能解决你的问题,请参考以下文章

带有 Statement.RETURN_GENERATED_KEYS 的 PreparedStatement

与 Statement.RETURN_GENERATED_KEYS 一起使用时 PreparedStatement 出现问题

java RETURN_GENERATED_KEYS

Statement.RETURN_GENERATED_KEYS 是不是会生成任何额外的往返行程来获取新创建的标识符?

Java PreparedStatement RETURN_GENERATED_KEYS 不起作用

获取数据库的自增主键