簡體   English   中英

對於 UUID 類型的列,在插入新行時返回 H2 數據庫中默認生成的主鍵值

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

當使用UUID數據類型作為表的主鍵時,並要求H2在插入新記錄時默認生成每個UUID值,如何訪問新生成的UUID值的值?

我在 Java 應用程序中使用純 JDBC 4.x,如果這有助於解決方案。


我知道SCOPE_IDENTITY函數返回一個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 類型文檔中所述

通用唯一標識符。 這是一個 128 位的值。 要存儲值,請使用 PreparedStatement.setBytes、setString 或 setObject(uuid)(其中 uuid 是 java.util.UUID)。 ResultSet.getObject 將返回一個 java.util.UUID。


我的示例基於您在問題中共享的鏈接Generate UUID values by default for each row on column of UUID type in H2 Database Engine

Statement::getGeneratedKeys

正如YCF_L 的評論和正確答案中所見,解決方案在於標准 JDBC:Call Statement::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_ ( \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();
        }


    }
}

運行時。

信息 - 報告生成的密鑰。

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

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

人:9c6ce984-151b-4e64-8334-d96e17be9525 | 傑西約翰遜

如果要一次插入多行而不是一行,請使用批處理。 請參閱: Java:使用 PreparedStatement 將多行插入 MySQL

如果您有多個自動生成的列,而不是這里看到的只有一個 UUID 列,請參閱YCF_L 的另一個答案

要從結果集中返回 UUID,您可以使用 FINAL TABLE:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM