Возврат параметра ROWID из оператора вставки с использованием соединения JDBC к оракулу - PullRequest
5 голосов
/ 25 марта 2009

Я не могу подобрать правильную магическую комбинацию для этой работы:


OracleDataSource ods = new oracle.jdbc.pool.OracleDataSource();
ods.setURL("jdbc:oracle:thin:app_user/pass@server:1521:sid");
DefaultContext conn = ods.getConnection();
CallableStatement st = conn.prepareCall("INSERT INTO tableA (some_id) VALUES (1) RETURNING ROWID INTO :rowid0");
st.registerReturnParameter(1, OracleTypes.ROWID);
st.execute();

Я получаю ошибку "Нарушение протокола". Если я изменяю на registerOutParameter (), я получаю уведомление, что я не зарегистрировал все возвращаемые переменные. Если я заверну оператор в PL / SQL, начнем; конец; блок, то я получаю параметр очень хорошо, используя обычный вызов registerOutParameter (). Я действительно предпочел бы избегать переноса всех моих операторов вставки в PL / SQL - так чего не хватает сверху?

Ответы [ 5 ]

15 голосов
/ 19 мая 2009

Обычно вы не хотите делать базу данных зависимой. Вместо OraclePreparedStatement вы должны использовать CallableStatement.

CallableStatement statement = connection.prepareCall("{call INSERT INTO tableA (some_id) VALUES (1) RETURNING ROWID INTO ? }");
statement.registerOutParameter( 1, Types.VARCHAR );

int updateCount = statement.executeUpdate();
if (updateCount > 0) {
   return statement.getString(1);
}
6 голосов
/ 04 мая 2009

Несколько вещей, которые вам нужно сделать

  • Изменить CallableStatement на OracleCallableStatement
  • Попробуйте вернуться в NUMBER, то есть: OracleTypes.Number

Пример кода для возврата информации из запроса:

OraclePreparedStatement pstmt = (OraclePreparedStatement)conn.prepareStatement(
       "delete from tab1 where age < ? returning name into ?");
pstmt.setInt(1,18);

/** register returned parameter
  * in this case the maximum size of name is 100 chars
  */
pstmt.registerReturnParameter(2, OracleTypes.VARCHAR, 100);

// process the DML returning statement
count = pstmt.executeUpdate();
if (count>0)
{
  ResultSet rset = pstmt.getReturnResultSet(); //rest is not null and not empty
  while(rset.next())
  {
    String name = rset.getString(1);
    ...
  }
}

Подробнее о расширениях JDBC для Oracle:

3 голосов
/ 25 марта 2009

Не знаю, применяется ли это или нет, поскольку вы не указываете, какую версию вы используете.

Из Оракула Металинк:

Причина

В драйвере JDBC 10.1.0.x возврат DML не поддерживается:

Согласно часто задаваемым вопросам JDBC: «10.1.0 (10g r1) Поддерживается ли возврат DML? Не в текущих драйверах. Тем не менее, у нас есть планы поддержать его в драйверах после 10.1.0. Мы на самом деле это так. "

Поскольку код приложения пытается использовать неподдерживаемые функции JDBC, возникают ошибки.

Решение

Обновите драйвер JDBC до 10.2.0.x, поскольку в соответствии с часто задаваемыми вопросами драйверы JDBC 10.2.0.x поддерживают возвращаемое предложение:

"10.2.0 (10 г р2) Поддерживается ли возврат DML? ДА! И это о времени. См. Руководство разработчика для деталей. «

EDIT Вы можете просто проверить версию JDBC, которую Oracle считает используемой с:

 // Create Oracle DatabaseMetaData object
  DatabaseMetaData meta = conn.getMetaData();

  // gets driver info:
  System.out.println("JDBC driver version is " + meta.getDriverVersion());

Если это показывает драйвер JDBC 10.2.0.x или более поздней, то у меня нет идей, и, возможно, запрос поддержки oracle в порядке ...

1 голос
/ 02 сентября 2014
PreparedStatement prepareStatement = connection.prepareStatement("insert...",
            new String[] { "your_primary_key_column_name" });

    prepareStatement.executeUpdate();

    ResultSet generatedKeys = prepareStatement.getGeneratedKeys();
    if (null != generatedKeys && generatedKeys.next()) {
         Long primaryKey = generatedKeys.getLong(1);
    }

Я нашел ответ, это прекрасно работает. Я могу вставить из JAVA и его возврата с помощью ключа.

Полная версия:

CREATE TABLE STUDENTS
(
   STUDENT_ID   NUMBER NOT NULL PRIMARY KEY,
   NAME         VARCHAR2 (50 BYTE),
   EMAIL        VARCHAR2 (50 BYTE),
   BIRTH_DATE   DATE
);


CREATE SEQUENCE STUDENT_SEQ
   START WITH 0
   MAXVALUE 9999999999999999999999999999
   MINVALUE 0;

И код Java

String QUERY = "INSERT INTO students "+
               "  VALUES (student_seq.NEXTVAL,"+
               "         'Harry', 'harry@hogwarts.edu', '31-July-1980')";

// load oracle driver
Class.forName("oracle.jdbc.driver.OracleDriver");

// get database connection from connection string
Connection connection = DriverManager.getConnection(
        "jdbc:oracle:thin:@localhost:1521:sample", "scott", "tiger");

// prepare statement to execute insert query
// note the 2nd argument passed to prepareStatement() method
// pass name of primary key column, in this case student_id is
// generated from sequence
PreparedStatement ps = connection.prepareStatement(QUERY,
        new String[] { "student_id" });

// local variable to hold auto generated student id
Long studentId = null;

// execute the insert statement, if success get the primary key value
if (ps.executeUpdate() > 0) {

    // getGeneratedKeys() returns result set of keys that were auto
    // generated
    // in our case student_id column
    ResultSet generatedKeys = ps.getGeneratedKeys();

    // if resultset has data, get the primary key value
    // of last inserted record
    if (null != generatedKeys && generatedKeys.next()) {

        // voila! we got student id which was generated from sequence
        studentId = generatedKeys.getLong(1);
    }

}

источник: http://viralpatel.net/blogs/oracle-java-jdbc-get-primary-key-insert-sql/

1 голос
/ 25 марта 2009

Попробуйте использовать ? вместо : rowid0 в строке SQL. У меня были проблемы с именованными параметрами и Oracle.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...