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

Difference between RETURN_GENERATED_KEYS and specifying the generated column names

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

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

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

我注意到 Spring 的 SimpleJdbcInsert class prefers the variant where the column names are specified: AbstractJdbcInsert.prepareStatementForGeneratedKeys

这是为什么?

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

这会对性能产生影响,因为:

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

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

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

方法 prepareStatement(String sql, String[] columnNames) and prepareStatement(String sql, int[] columnIndexes) 提供更多控制(如果支持),关于 return 编辑的内容。如果您确切知道需要或想要哪些字段,则可以指定它们并准确获取这些字段,而不必担心使用 RETURN_GENERATED_KEYS.

时的行为差异

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