Использование Oracle RETURNING INTO в Java (JDBC, подготовленное выражение)

Я использую JDBC для выполнения инструкции Oracle, которая выглядит так:

"INSERT INTO MYTABLE(MYDATA) VALUES(?) RETURNING MY_CALCULATED_DATA INTO ?"
// MYTABLE def makes MY_CALCULATED_DATA be auto-generated by DB on insert

Я нашел несколько способов вызвать выражение выше в Java, в основном:

  • Использование OraclePreparedStatement:

    ps = (OraclePreparedStatement)conn.prepareStatement(sql);
    ps.setString(1, "myvalue");
    ps.registerReturnParameter(2, Types.VARCHAR);
    ps.execute();
    rs = ps.getReturnResultSet();
    rs.next();
    System.out.print(rs.getString(1));
    
  • Использование CallableStatement:

    cs = conn.prepareCall(sql);
    cs.setString(1, "myvalue");
    cs.registerOutParameter(2, Types.VARCHAR);
    cs.execute();
    System.out.print(cs.getString(1));
    

Вопросы:

  • Метод # 2 выбрасывает "SQLException: не все зарегистрированные параметры возврата", НО, если я завершу инструкцию SQL в " BEGIN..END;" - тогда метод # 2 работает просто отлично.
    • Почему метод №1 работает без " BEGIN..END" , но для метода # 2 требуется " BEGIN..END" для работы?
    • Какое "волшебное" " BEGIN..END" относится к заявлению, так что проблема "не все зарегистрированные параметры" внезапно решает сам?

  • Есть ли какой-то третий, лучший способ сделать это?

Спасибо, AG.

Ответы

Ответ 1

Поскольку параметры, указанные в возвращаемых предложениях, обрабатываются по-другому по сравнению с обычными выходными параметрами (getReturnResultSet vs getResultSet vs возвращает параметры в callablestatement).
Они должны обрабатываться с помощью OraclePreparedStatement. Во втором случае, когда вы завершаете инструкцию insert в начале..., вставка обрабатывается самой базой данных, а al jdbc видит анонимный блок plsql.
http://docs.oracle.com/cd/E11882_01/java.112/e16548/oraint.htm#BABJJDDA

Ответ 2

Чтобы получить авто сгенерированный ключ, у нас есть метод getGeneratedKeys в процессе подготовки, который возвращает результат, содержащий ключевое значение, все, что нам нужно, это имя столбца ключа доступа для подготовки

pstm = con.prepareStatement("insert query",new String[]{primarykeycolumnname});
int i = pstm.executeUpdate();
if (i > 0) 
{
    ResultSet rs = pstm.getGeneratedKeys();
    while(rs.next())
    {
        System.out.println(rs.getString(1)); 
    }
}