Возврат значения первичного ключа, сгенерированного по умолчанию в базе данных H2 после INSERT новой строки, для столбца типа UUID - PullRequest
0 голосов
/ 23 декабря 2018

При использовании UUID data type в качестве первичного ключа таблицы и запросе H2 к генерирует каждое значение UUID по умолчанию после INSERT новогозапишите, как один получает доступ к недавно сгенерированному значению UUID ?

Я использую простой JDBC 4.x в приложении Java, если это помогает с решением.


Я знаю, SCOPE_IDENTITY функция возвращает long для ключа, сгенерированного в столбце, помеченном как IDENTITY для автоматически увеличивающегося порядкового номера.Но я использую UUID, а не возрастающее число в качестве типов столбцов первичного ключа.

Ответы [ 2 ]

0 голосов
/ 24 декабря 2018

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


    }
}

При запуске.

INFO - Сгенерирована отчетностьkeys.

сгенерированные ключи: 9c6ce984-151b-4e64-8334-d96e17be9525

INFO - Отчет о всех строках таблицы person_.

Person: 9c6ce984-151b-4e64-8334-d96e17be9525 |Джесси Джонсон

Если вы хотите вставить несколько строк одновременно, а не одну, используйте пакетную обработку.См .: Java: вставка нескольких строк в MySQL с помощью PreparedStatement .

Если у вас есть автоматически сгенерированные несколько столбцов, а не только один единственный столбец UUID, видимый здесь, см. other Answer by YCF_L .

0 голосов
/ 24 декабря 2018

Укажите имя (имена) сгенерированных столбцов

При подготовке вашего оператора вы можете при желании передать массив имен столбцов, для которых генерируется значение по умолчанию.Только для одного столбца первичного ключа это означает массив из одного значения.

См. Метод: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.


Мой пример, основанный на ссылке, которую вы указали в своем вопросе Создание значений UUID по умолчанию длякаждая строка в столбце типа UUID в H2 Database Engine

...