使用UUID数据type作为表的主键,并在插入新记录时要求H2 generate each UUID value by default时,如何访问该值新生成的UUID值?
如果有解决方案,我正在Java应用程序中使用纯JDBC 4.x。
我知道SCOPE_IDENTITY
函数为在自动递增序列号标记为long
的列上生成的密钥返回IDENTITY
。但是我使用UUID而不是递增数字作为主键列类型。
答案 0 :(得分:3)
在准备语句时,可以选择传递要为其生成默认值的列名称的数组。仅对于单个主键列,这意味着一个值的数组。
请参见方法:
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(..)
并将其转换为H2 UUID Type文档中所述的java.util.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中共享的链接
答案 1 :(得分:2)
Statement::getGeneratedKeys
从注释和correct Answer by YCF_L中可以看出,解决方案在于标准的JDBC:调用Statement::getGeneratedKeys
。这将产生ResultSet
的键值,该键值是在该语句的先前使用中默认生成的。这适用于PreparedStatement
,并且适用于自动生成UUID值作为主键。
Statement.RETURN_GENERATED_KEYS
要注意的是,默认情况下,您不执行 not 来获取生成的密钥。您必须通过向您的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();
}
}
}
运行时。
INFO-报告生成的密钥。
生成的密钥: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。