Return H2 数据库在插入新行时默认生成的主键值,用于 UUID 类型列

Return primary key value generated by default in H2 database upon INSERT of new row, for UUID type column

当在插入新记录时使用 UUID data type as the primary key of a table, and asking H2 to 如何访问新生成的 UUID 值的值?

我在 Java 应用程序中使用纯 JDBC 4.x,如果这有助于解决问题。


我知道 SCOPE_IDENTITY 函数 returns a long 用于在标记为 IDENTITY 的列上生成的键,用于自动递增序列号。但是我使用 UUID 而不是递增数字作为我的主键列类型。

指定生成列的名称

在准备语句时,您可以选择传递一个列名数组,这些列的名称将为其生成默认值。对于您的单个主键列,这意味着一个值的数组。

查看方法:
Connection::prepareStatement​( String sql, String[] columnNames )

示例代码。

// here you can specify the list of returned attributes, in your case just the data
String[] returnedAttributes = {"data"};
String insertQuery = "insert into test(id) values(1);";
try 
(
    PreparedStatement insertStatement = conn.prepareStatement(insertQuery, returnedAttributes);
) 
{
    int rows = insertStatement.executeUpdate();
    if (rows == 0) 
    {
        throw new SQLException("Failed of insertion");
    }
    try (ResultSet rs = insertStatement.getGeneratedKeys()) {
        if (rs.next()) 
        {
             java.util.UUID uuid = (java.util.UUID) rs.getObject("data");
             System.out.println(uuid);
        }
    }
}

备注

要获取 UUID 类型,您必须使用 getObjct(..) 并将其转换为 java.util.UUID,如 H2 UUID Type

的文档中所述

Universally unique identifier. This is a 128 bit value. To store values, use PreparedStatement.setBytes, setString, or setObject(uuid) (where uuid is a java.util.UUID). ResultSet.getObject will return a java.util.UUID.


我的示例基于您在问题中分享的 link

Statement::getGeneratedKeys

如评论和 , the solution lies in standard JDBC: Call Statement::getGeneratedKeys. This yields a ResultSet of the key values generated by default in the previous use of that statement. This works with PreparedStatement 所示,并使用自动生成的 UUID 值作为主键。

Statement.RETURN_GENERATED_KEYS

要注意的是,默认情况下您不会取回生成的密钥。您必须通过向 Connection::prepareStatement call. The extra argument is an int, using a constant defined on the Statement interface, Statement.RETURN_GENERATED_KEYS. In modern Java that would have likely have been defined as an Enum, but JDBC 日期追溯到 Java 最早的日子传递一个额外的参数来激活此功能,因此该参数是一个简单的 int.

示例应用程序

这是单个文件中的完整示例应用程序。

package work.basil.example.h2.auto_uuid;

import java.sql.*;
import java.util.UUID;

public class App {
    public static void main ( String[] args ) {
        App app = new App();
        app.doIt();
    }

    private void doIt ( ) {
        
        try {
            Class.forName( "org.h2.Driver" );
        } catch ( ClassNotFoundException e ) {
            e.printStackTrace();
        }

        try (
                Connection conn = DriverManager.getConnection( "jdbc:h2:mem:auto_uuid_example_db;DB_CLOSE_DELAY=-1" ) ; // Set `DB_CLOSE_DELAY` to `-1` to keep in-memory database in existence after connection closes.
                Statement stmt = conn.createStatement() ;
        ) {
            String sql = "CREATE TABLE person_ ( \n" +
                    "  pkey_ UUID NOT NULL DEFAULT RANDOM_UUID() PRIMARY KEY , \n" +
                    "  name_ VARCHAR NOT NULL \n" +
                    ");";
            stmt.execute( sql );

            // Insert row.
            sql = "INSERT INTO person_ ( name_ ) \n";
            sql += "VALUES ( ? ) \n";
            sql += ";";
            try (
                    PreparedStatement pstmt = conn.prepareStatement( sql , Statement.RETURN_GENERATED_KEYS ) ;
            ) {

                pstmt.setString( 1 , "Jesse Johnson" );
                pstmt.executeUpdate();

                ResultSet rs = pstmt.getGeneratedKeys();
                System.out.println( "INFO - Reporting generated keys." );
                while ( rs.next() ) {
                    UUID uuid = rs.getObject( 1 , UUID.class );
                    System.out.println( "generated keys: " + uuid );
                }

            }

            // Dump all rows.
            System.out.println( "INFO - Reporting all rows in table `person_`." );
            sql = "SELECT * FROM person_";
            try ( ResultSet rs = stmt.executeQuery( sql ) ; ) {
                while ( rs.next() ) {
                    UUID pkey = rs.getObject( "pkey_" , UUID.class );
                    String name = rs.getString( "name_" );
                    System.out.println( "Person: " + pkey + " | " + name );
                }
            }

        } catch ( SQLException e ) {
            e.printStackTrace();
        }


    }
}

当运行.

INFO - Reporting generated keys.

generated keys: 9c6ce984-151b-4e64-8334-d96e17be9525

INFO - Reporting all rows in table person_.

Person: 9c6ce984-151b-4e64-8334-d96e17be9525 | Jesse Johnson

如果您想一次插入多行,而不是一行,请使用批处理。参见:Java: Insert multiple rows into MySQL with PreparedStatement.

如果您有多个自动生成的列,而不是此处看到的只有一个 UUID 列,请参阅

对于结果集中的 return UUID,您可以使用 FINAL TABLE:

SELECT ID FROM FINAL TABLE ( INSERT INTO PERSON(NAME) VALUES('Joe'))