[英]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 而不是递增数字作为我的主键列类型。
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
。
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.