2015-04-29 8 views
1

Я запускаю SQL Anywhere 16.0 и пытаюсь использовать мои шаблоны Spring JDBC. То, что мне нужно сделать, очень просто: вставьте строку в таблицу, а затем верните автоматически генерируемое значение идентификатора.Функция getGeneratedKeys не поддерживается этой базой данных

public int log() { 
    SimpleJdbcInsert insertActor = 
      new SimpleJdbcInsert(ds) 
      .withTableName("DBA.REQUESTS") 
      .usingGeneratedKeyColumns("REQUEST_ID"); 

    Map<String, Object> parameters = new HashMap<String, Object>(); 
    parameters.put("USER_ID", userId); 
    parameters.put("DATA_TYPE_ID", getProductSku()); 
    parameters.put("PRICE", price); 
    // ...more parameters 

    Number requestIdNumber = insertActor.executeAndReturnKey(parameters); 
    return requestIdNumber.intValue(); 
} 

Но весна неоднократно дает мне ошибку

org.springframework.dao.InvalidDataAccessResourceUsageException: 
    The getGeneratedKeys feature is not supported by this database 

Водитель Я использую должен поддерживать JDBC 4.0 (библиотека dbjdbc16.dll и находится в пути, и sajdbc4.jar в каталог Tomcat lib). Соответствующая информация подключения к базе данных с Tomcat является

<Resource auth="Container" description="Pooled connection to the web database" 
    driverClassName="sybase.jdbc4.sqlanywhere.IDriver" 
    maxActive="30" maxIdle="5" maxWait="10000" name="jdbc/web" 
    removeAbandoned="true" 
    removeAbandonedTimeout="60" 
    type="javax.sql.DataSource" 
    url="jdbc:sqlanywhere:Server=web;UID=xxx;PASSWORD=xxx;port=xxxx;LINKS=tcpip(PORT=xxxx)"/> 

и контекст Spring приложения для источника данных является

<jee:jndi-lookup id="dbDataSource" jndi-name="jdbc/web" 
      expected-type="javax.sql.DataSource" /> 

Так что мой вопрос, есть ли способ настроить вещи лучше, чтобы этот тип заявления работает? OR Если база данных по-настоящему не поддерживает это на каком-то фундаментальном уровне, есть ли не уродливая альтернатива для меня, чтобы вставлять значения и возвращать сгенерированный идентификатор.

UPDATE: Похоже, что драйвер базы данных не поддерживает эту функцию. Предложения здесь и в другом месте должны были сделать INSERT, чем SELECT сразу после. Проблема, конечно, в том, что если другой пользователь вставит в таблицу между этими двумя утверждениями, вы получите неправильное значение, и в этом случае это будет очень плохо.

Моим обходным решением сейчас является использование блокировки на уровне класса в соответствующем DAO и выбор по нескольким столбцам (не только IDENTITY), так что я могу быть 99.9% уверен, что получаю ту же строку назад. Достаточно хорошо работать. Тем не менее, я бы предпочел иметь транзакционный способ блокировки таблицы. Я не думаю обозначение функции @Transactional будет работать для этого, правильно, так как это просто задерживает фиксацию до тех пор, пока все утверждения не будут успешными?

+0

Помогает ли [этот вопрос] (http://stackoverflow.com/q/16932814/2144390)? –

+0

Нет, к сожалению, это именно то, что я сделал. –

+1

Поддерживает ли драйвер поддержку возврата сгенерированного ключа? Это дополнительная функция в спецификации JDBC 4.0. Вы можете определить, работает оно или нет, проверяя метаданные базы данных JDBC с помощью метода «DatabaseMetaData.supportsGetGeneratedKeys». –

ответ

0

Я вообще не эксперт JDBC, поэтому я не могу ответить на вопрос напрямую, но могу сказать, что сервер SQL Anywhere, безусловно, обладает этой способностью. Если материал JDBC не работает, вы можете использовать переменную @@identity. Извлечение select @@identity, которое вернет автоматически сгенерированное значение для последнего оператора.

Отказ от ответственности: Я работаю для SAP в SQL Anywhere engineering.

+0

Спасибо, Грэм! К сожалению, это не касается случая, когда другой пользователь выполнил вставку перед запуском select. Если они есть, вы получите неправильное значение, и в этом случае это будет очень плохо. Если есть способ (JDBC) заблокировать таблицу до тех пор, пока не будет выполнен SELECT, это будет идеально. –

+0

Нет, это не тот случай. Извинения, мое описание было неполным - 'select @@ identity' возвращает автоматически сгенерированное значение для последнего оператора insert _done на текущем соединении_.Поэтому, если ваше соединение вставляет строку, то другое соединение вставляет строку, 'select @@ identity' на вашем соединении возвращает идентификатор строки _you_. –

+0

Очень интересно. Я использую пул соединений, хотя - возможно, два пользователя будут делиться соединением, я думаю, если есть какой-то способ предотвратить это? –