Howto возвращает идентификаторы на вставках с Ibatis (с ключевым словом RETURNING)

Я использую iBatis/Java и Postgres 8.3. Когда я делаю вставку в ibatis, мне нужно вернуть id.
Я использую следующую таблицу для описания моего вопроса:
CREATE TABLE sometable ( id serial NOT NULL, somefield VARCHAR(10) );
Последовательность sometable_id_seq получает автогенерирование, запустив инструкцию create.

В настоящее время я использую следующую карту sql:

<insert id="insertValue" parameterClass="string" >
 INSERT INTO sometable ( somefield ) VALUES ( #value# );
 <selectKey keyProperty="id" resultClass="int">
  SELECT last_value AS id FROM sometable_id_seq
 </selectKey>
</insert>

Кажется, это способ ibatis восстановить вновь вставленный идентификатор. Ibatis сначала запускает оператор INSERT, а затем запрашивает последовательность для последнего id.
У меня есть сомнения, что это будет работать со многими параллельными вставками. (обсуждался в этом вопросе)

Я хотел бы использовать следующую инструкцию с помощью ibatis:
INSERT INTO sometable ( somefield ) VALUES ( #value# ) RETURNING id;

Но когда я пытаюсь использовать его в <insert> sqlMap, ibatis не возвращает идентификатор. Кажется, что требуется тег <selectKey>.

Итак, возникает вопрос:

Как я могу использовать вышеуказанное утверждение с помощью ibatis?

Ответы

Ответ 1

Элемент <selectKey> является дочерним элементом элемента <insert>, а его содержимое выполняется перед основным оператором INSERT. Вы можете использовать два подхода.

Получить ключ после того, как вы вставили запись

Этот подход работает в зависимости от вашего драйвера. Threading может быть проблемой с этим.

Извлечение ключа перед вставкой записи

Этот подход позволяет избежать проблем с потоками, но это большая работа. Пример:

<insert id="insert">
  <selectKey keyProperty="myId"
             resultClass="int">
    SELECT nextVal('my_id_seq')
  </selectKey>
  INSERT INTO my
    (myId, foo, bar)
  VALUES
    (#myId#, #foo#, #bar#)
</insert>

На стороне Java вы можете сделать

Integer insertedId = (Integer) sqlMap.insert("insert", params)

Это даст вам ключ, выбранный из последовательности my_id_seq.

Ответ 2

Вот простой пример:

<statement id="addObject"
        parameterClass="test.Object"
        resultClass="int">
        INSERT INTO objects(expression, meta, title,
        usersid)
        VALUES (#expression#, #meta#, #title#, #usersId#)
        RETURNING id
</statement>

И в коде Java:

Integer id = (Integer) executor.queryForObject("addObject", object);
object.setId(id);

Этот способ лучше, чем использование:

  • Это проще,
  • Он не просил узнать имя последовательности (что обычно скрыто от разработчиков postgresql).