Вставьте запись с помощью PreparedStatementCreator (должна работать на Oracle и PostgreSQL)

Я пытаюсь использовать инструкцию Spring Jdbc Prepared для вставки записей в таблицу. Этот код должен работать на Postgres и Oracle. Мне нужно прочитать вставленный ключ записи после вставки.

Я нашел приведенный ниже код в главе JDBC документации Spring, и в нем говорится, что «это работает с Oracle».
См. ссылку здесь (раздел 12.2.8).

Он прекрасно работает на Postgres, вставляет запись, и я могу прочитать вставленный ключ записи с помощью keyHolder. Однако в Oracle это не удается с сообщением об ошибке ниже...

[junit] STDOUT [ERROR] [2011.11.04 01:26:04] ..... - Тест ...... не пройден. [junit] Сообщение: PreparedStatementCallback; SQL []; ORA-01400: невозможно вставить NULL в ("SOME_USER"."SOME_TABLE"."ID") [junit] ; вложенным исключением является java.sql.SQLIntegrityConstraintViolationException: ORA-01400: невозможно вставить NULL в («SOME_USER». «SOME_TABLE». «ID»)

Вот код...

        KeyHolder keyHolder = new GeneratedKeyHolder();
    jdbcTemplate.update(new PreparedStatementCreator()
    {
        public PreparedStatement createPreparedStatement(Connection connection) throws SQLException
        {
            PreparedStatement ps = connection.prepareStatement("insert into some_table(xxx_name,xxx_date), new String[] { "id" });
            ps.setString(1, "some name");
            ps.setDate(2, "some date");
            return ps;
        }
    }, keyHolder);

Примечание. Я использую ojdbc6.jar (JAR JDBC JAR), банк Commons dbcp.

Вот applicationContext dataSource bean

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="${db.driver}" />
    <property name="url" value="${db.url}" />
    <property name="username" value="${db.username}" />
    <property name="password" value="${db.password}" />
</bean>

У меня есть последовательности, присутствующие как в Postgres, так и в Oracle, для таблицы some_table_id_seq. Я должен заставить этот код работать для Postgres (работает на машинах разработчиков) и Oracle (работает на производстве). Любая помощь/идеи приветствуются. Спасибо.


person aug70co    schedule 05.11.2011    source источник
comment
Существует нет Postgre. Это PostgreSQL или Postgres для краткости.   -  person Erwin Brandstetter    schedule 05.11.2011


Ответы (1)


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

У Oracle нет такой концепции. Если вы не хотите вызывать sequence.nextval вручную (что было бы возможно и с Postgres), вам нужно создать триггер, который назначает следующее значение последовательности для этого столбца.

CREATE OR REPLACE TRIGGER trg_ins_some_table
  BEFORE INSERT ON some_table
  FOR EACH ROW
BEGIN
   :new.id := some_table_id_seq.nextval;
END;
/
person a_horse_with_no_name    schedule 05.11.2011
comment
Хотя в итоге я реализовал свое собственное решение, я принимаю ваш ответ как принятый ответ. - person aug70co; 06.11.2011
comment
Я отказался от попыток использовать один и тот же запрос для обеих баз данных, поэтому я реализовал карту со специальными именами ключей и запросами, для Postgres он выбирает разные запросы на вставку, а для Oracle у него разные запросы с использованием xxx_id_seq.nextval. - person aug70co; 06.11.2011