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

2022-04-08 00:00:00 sql uuid jdbc java h2

使用UUID数据type作为表的主键,并在插入新记录时要求h2generate each UUID value by default,如何获取新生成的UUID值?

我在Java应用程序中使用纯JDBC 4.x,如果这对解决方案有帮助的话。


I KnowSCOPE_IDENTITY函数为在标记为IDENTITY的列上为自动递增的序列号生成的键返回long。但我使用UUID而不是递增数字作为我的主键列类型。


解决方案

Statement::getGeneratedKeys

如注释和correct Answer by YCF_L所示,解决方案在于标准的JDBC:CallStatement::getGeneratedKeys。这将生成该语句的上一次使用中默认生成的键值的ResultSet。它与PreparedStatement配合使用,并将自动生成的UUID值作为主键。

Statement.RETURN_GENERATED_KEYS

问题是,在默认情况下,而不是获取的是生成的密钥。您必须通过向Connection::prepareStatement调用传递额外参数来激活此功能。额外的参数是int,使用Statement接口上定义的常量Statement.RETURN_GENERATED_KEYS。在现代Java中,这很可能被定义为Enum,但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_ ( 
" +
                    "  pkey_ UUID NOT NULL DEFAULT RANDOM_UUID() PRIMARY KEY , 
" +
                    "  name_ VARCHAR NOT NULL 
" +
                    ");";
            stmt.execute( sql );

            // Insert row.
            sql = "INSERT INTO person_ ( name_ ) 
";
            sql += "VALUES ( ? ) 
";
            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();
        }


    }
}

运行时。

信息报告生成的密钥。

生成密钥:9c6ce984-151b-4e64-8334-d96e17be9525

INFO-报告表person_中的所有行。

联系人:9c6ce984-151b-4e64-8334-d96e17be9525|Jesse Johnson

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

如果您有多个自动生成的列,而不仅仅是此处看到的单个UUID列,请参阅other Answer by YCF_L。

相关文章