简体   繁体   English

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

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

When using a UUID data type as the primary key of a table, and asking H2 to generate each UUID value by default upon INSERT of a new record, how does one access the value of the newly generated UUID value?当使用UUID数据类型作为表的主键时,并要求H2在插入新记录时默认生成每个UUID值,如何访问新生成的UUID值的值?

I am using plain JDBC 4.x in a Java app, if that helps with a solution.我在 Java 应用程序中使用纯 JDBC 4.x,如果这有助于解决方案。


I know SCOPE_IDENTITY function returns a long for a key generated on a column marked as IDENTITY for an auto-incrementing sequence number.我知道SCOPE_IDENTITY函数返回一个long用于在标记为IDENTITY的列上生成的键,用于自动递增序列号。 But I am using UUID rather than an incrementing number as my primary key column types.但我使用 UUID 而不是递增数字作为我的主键列类型。

Specify name(s) of generated columns指定生成列的名称

When preparing your statement, you can optionally pass an array of the names of columns for which a default value is being generated.准备语句时,您可以选择传递为其生成默认值的列的名称数组。 For just your single primary key column, that means an array of one value.对于您的单个主键列,这意味着一个值的数组。

See the method:见方法:
Connection::prepareStatement( String sql, String[] columnNames )

Example code.示例代码。

// 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);
        }
    }
}

Note笔记

to get the UUID type you have to use getObjct(..) and cast it to java.util.UUID as stated in the documentation of H2 UUID Type要获取 UUID 类型,您必须使用getObjct(..)并将其转换为java.util.UUID ,如H2 UUID 类型文档中所述

Universally unique identifier.通用唯一标识符。 This is a 128 bit value.这是一个 128 位的值。 To store values, use PreparedStatement.setBytes, setString, or setObject(uuid) (where uuid is a java.util.UUID).要存储值,请使用 PreparedStatement.setBytes、setString 或 setObject(uuid)(其中 uuid 是 java.util.UUID)。 ResultSet.getObject will return a java.util.UUID. ResultSet.getObject 将返回一个 java.util.UUID。


My example based on the link you shared in your question Generate UUID values by default for each row on column of UUID type in H2 Database Engine我的示例基于您在问题中共享的链接Generate UUID values by default for each row on column of UUID type in H2 Database Engine

Statement::getGeneratedKeys

As seen in comments and the correct Answer by YCF_L , the solution lies in standard JDBC: Call Statement::getGeneratedKeys .正如YCF_L 的评论和正确答案中所见,解决方案在于标准 JDBC:Call Statement::getGeneratedKeys This yields a ResultSet of the key values generated by default in the previous use of that statement.这将生成一个ResultSet ,其中包含在先前使用该语句时默认生成的键值。 This works with PreparedStatement , and works with auto-generating UUID values as the primary key.这适用于PreparedStatement ,并使用自动生成的 UUID 值作为主键。

Statement.RETURN_GENERATED_KEYS

The catch is that by default you do not get back generated keys.问题是默认情况下您不会取回生成的密钥。 You must activate this feature by passing an extra argument to your Connection::prepareStatement call.您必须通过将额外参数传递给Connection::prepareStatement调用来激活此功能。 The extra argument is an int , using a constant defined on the Statement interface, Statement.RETURN_GENERATED_KEYS .额外的参数是一个int ,使用在Statement接口上定义的常量Statement.RETURN_GENERATED_KEYS In modern Java that would have likely have been defined as an Enum , but JDBC dates back to the earliest days of Java, so the argument is a simple int .在现代 Java 中,它可能被定义为Enum ,但JDBC可以追溯到 Java 的早期,因此参数是一个简单的int

Example app示例应用

Here is a complete example app, in a single file.这是一个完整的示例应用程序,位于单个文件中。

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();
        }


    }
}

When run.运行时。

INFO - Reporting generated keys.信息 - 报告生成的密钥。

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

INFO - Reporting all rows in table person_ . INFO - 报告表person_中的所有行。

Person: 9c6ce984-151b-4e64-8334-d96e17be9525 |人:9c6ce984-151b-4e64-8334-d96e17be9525 | Jesse Johnson杰西约翰逊

If you want to insert multiple rows at a time, rather than one, use batching.如果要一次插入多行而不是一行,请使用批处理。 See: Java: Insert multiple rows into MySQL with PreparedStatement .请参阅: Java:使用 PreparedStatement 将多行插入 MySQL

If you have multiple columns being auto-generated, rather than just the one single UUID column seen here, see the other Answer by YCF_L .如果您有多个自动生成的列,而不是这里看到的只有一个 UUID 列,请参阅YCF_L 的另一个答案

To return UUID from resultset you could use FINAL TABLE:要从结果集中返回 UUID,您可以使用 FINAL TABLE:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 TIMESTAMP 列的 H2 数据库默认值 - H2 database default value of TIMESTAMP column 使用JAVA UUID作为主键时,H2内存数据库错误“数据转换错误转换” - H2 in-memory database error “Data conversion error converting” when using JAVA UUID as primary key H2数据库-在主键冲突时替换 - H2 Database - on primary key conflict replace 如何返回生成的 UUID 主键 - How to return generated UUID primary key 将h2数据库上的列的默认值更改为当前时间戳 - Change default value for column on h2 database to current timestamp 即使通过Spring Boot在架构中指定H2数据库也无法在列中设置默认值 - H2 database not able to set default value in a column even though specified in the schema through Spring Boot H2 数据库与 Hibernate 错误导致:org.h2.jdbc.JdbcSQLIntegrityConstraintViolationException:唯一索引或主键 - H2 Database with Hibernate error Caused by: org.h2.jdbc.JdbcSQLIntegrityConstraintViolationException: Unique index or primary key H2数据库列大小 - H2 database column size 尝试在 Spring 启动应用程序中将行插入 H2 db 时出现主键冲突异常 - Primary Key violation exception when trying to insert rows into H2 db in Spring boot application INSERT IGNORE在mysql模式下使用h2引发主键冲突 - INSERT IGNORE throws primary key violation using h2 in mysql mode
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM