Вернуть порядковый номер на вставке - PullRequest
0 голосов
/ 20 октября 2018

После добавления заказа в базу данных HSQL через мой объект OrderDAO я хочу иметь возможность получить порядковый номер, который был назначен заказу при вставке.

У меня есть это для моего PreparedStatement:

public long saveOrder(Order order) {
    long orderId = 0;
    try (Connection conn = MyDataSource.getDataSource().getConnection();
         PreparedStatement ps = conn.prepareStatement("INSERT INTO orders(id, order_number) VALUES (NEXT VALUE FOR seq1, ?)",
                                                            PreparedStatement.RETURN_GENERATED_KEYS)) {

        ps.setString(1, order.getOrderNumber());
        ps.execute();

        ResultSet rs = ps.getResultSet();
        if (rs.next()) {
            orderId = rs.getLong(1);
        }

    } catch (Exception e) {
        throw new RuntimeException(e);
    }
    return orderId;
}

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

Куда я с этим ошибаюсь?

Ответы [ 2 ]

0 голосов
/ 21 октября 2018

Есть две проблемы с вашим кодом:

  1. Вы используете неправильный метод для получения набора результатов сгенерированных ключей.Сгенерированный результирующий набор ключей можно получить только с помощью getGeneratedKeys() (или, по крайней мере, именно этого требует спецификация JDBC).

    Вам нужно изменить код, чтобы использовать ps.getGeneratedKeys() вместо ps.getResultSet()

  2. Другая проблема в том, что ваш код предполагает нестандартное поведение сгенерированных ключей: ваша вставка на самом деле не использует сгенерированный ключ в том смысле, в каком подразумевается спецификация JDBC, поскольку вы генерируете идентификатор воператор вставки самостоятельно (используя NEXT VALUE FOR seq1), вместо того, чтобы генерировать ключ как побочный эффект оператора вставки (например, с помощью столбца идентификаторов или триггера).

    HSQLDB не возвращает сгенерированный ключ вэта ситуация, поскольку она не рассматривает id как сгенерированный столбец.Вместо этого вам нужно либо определить столбец как столбец идентификаторов (и не указывать его явно во вставке), либо, альтернативно, явно указать возвращаемый столбец.

    Для создания столбца идентификаторов см.документация HSQLDB.Чтобы явно указать возвращаемый столбец, замените

    conn.prepareStatement("<query>", PreparedStatement.RETURN_GENERATED_KEYS)
    

    либо указанием индекса возвращаемых столбцов (т. Е. 1 - это первый столбец):

    conn.prepareStatement("<query>", new int[] { 1 })
    

    илиспецификация имени столбца возвращаемых столбцов

    conn.prepareStatement("<query>", new String[] { "id" })
    

Ваш окончательный код должен выглядеть примерно так:

try (PreparedStatement ps = conn.prepareStatement(
         "INSERT INTO orders(id, order_number) VALUES (NEXT VALUE FOR seq1, ?)",
         new String[] { "id" })) {
    ps.setString(1, order.getOrderNumber());
    ps.execute();

    try (ResultSet rs = stmt.getGeneratedKeys()) {
        if (rs.next()) {
            return rs.getLong(1);
        }
    }
}
0 голосов
/ 20 октября 2018

Исходя из этого ТАКОГО вопроса и ответа , ваш синтаксис должен выглядеть примерно так:

Connection conn = MyDataSource.getDataSource().getConnection();
long orderId = 0;
String sql = "INSERT INTO orders (id, order_number) VALUES (NEXT VALUE FOR seq1, ?)";
PreparedStatement ps = conn.prepareStatement(sql, RETURN_GENERATED_KEYS);
ps.setString(1, order.getOrderNumber());
int numAffected = ps.executeUpdate();
ResultSet rs = ps.getGeneratedKeys();
if (rs.next()) {
    orderId = rs.getLong(1);
}
...