После вставки заказа в базу данных 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;
}
Я бы предположил, что после выполнения запроса и запроса его набора результатов первым столбцом в наборе результатов будет порядковый номер. Но, похоже, у меня так не получается.
Где я ошибаюсь в этом?
Добавил код. И я использую hsqldb в памяти.
Выполните первый запрос, чтобы получить следующее значение из последовательности, затем используйте результат в качестве параметра для второго запроса.




Исходя из этот ТАК вопрос и ответ, ваш синтаксис должен быть примерно таким:
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);
}
Проверка количества обновлений совершенно не нужна
@MarkRotteveel entirely unnecessary ... значит, вы говорите, что не существует мыслимого сценария, при котором количество обновлений DML не равно единице?
Это вставка, которая либо завершилась успешно и вставила строку, либо не удалась с исключением. Также учтите, что счетчик обновлений сложен и в некоторых базах данных может возвращать значение выше 1, даже если была вставлена только 1 строка (например, если триггер вставил запись аудита, это может быть включено в счетчик обновлений в некоторых системах баз данных).
В вашем коде есть две проблемы:
Вы используете неправильный метод для получения набора результатов сгенерированных ключей. Сгенерированный набор результатов ключей можно получить только с помощью getGeneratedKeys() (или, по крайней мере, этого требует спецификация JDBC).
Вам нужно изменить свой код, чтобы использовать ps.getGeneratedKeys() вместо ps.getResultSet()
Другая проблема заключается в том, что ваш код предполагает нестандартное поведение сгенерированных ключей: ваша вставка на самом деле не использует сгенерированный ключ в том смысле, который предполагает спецификация 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);
}
}
}
Покажите нам код, который вы пробовали, а также сообщите нам, какую базу данных и драйвер вы используете. Не все БД могут поддерживать сгенерированные ключи, и не все поддерживают это одинаково.