2013-07-31 4 views
9

Последние Java JDBC-драйверы для postgres утверждают, что поддерживают UUID изначально; работая с Postgres 9.2 (mac).Postgres UUID JDBC не работает

Действительно, когда используется PreparedStatement, я могу пройти через код драйвера и даже пройти через специализированную функцию setUuid в AbstractJdbc3gStatement.java. По всем показаниям, он должен «просто работать».

Однако, это не работает. База данных швыряет назад ошибку, которую я получаю таким образом:

Caused by: org.postgresql.util.PSQLException: ERROR: operator does not exist: uuid = bytea 
    Hint: No operator matches the given name and argument type(s). You might need to add explicit type casts. 
    Position: 139 
    at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2157) ~[postgresql-9.2-1002.jdbc4.jar:na] 

Да, действительно, setUuid в драйвере JDBC делает передачу, что в BYTEA:

private void setUuid(int parameterIndex, UUID uuid) throws SQLException { 
     if (connection.binaryTransferSend(Oid.UUID)) { 
      byte[] val = new byte[16]; 
      ByteConverter.int8(val, 0, uuid.getMostSignificantBits()); 
      ByteConverter.int8(val, 8, uuid.getLeastSignificantBits()); 
      bindBytes(parameterIndex, val, Oid.UUID); 
     } else { 
      bindLiteral(parameterIndex, uuid.toString(), Oid.UUID); 
     } 
    } 

Что дает? Есть ли какая-то волшебная руна в реальной базе данных, чтобы благословить это преобразование?

+1

Вы можете разместить фактическое PreparedStatement вы пытаетесь запустить? – Rafael

ответ

20

(a) Покажите нам свой код.

(b) См. Мой блог UUID Values From JDBC to Postgres для обсуждения и примера кода.

// Generate or obtain data to store in database. 
java.util.UUID uuid = java.util.UUID.randomUUID(); // Generate a random UUID. 
String foodName = "Croissant"; 
// JDBC Prepared Statement. 
PreparedStatement preparedStatement = conn.prepareStatement("INSERT INTO food_ (pkey_, food_name_ ) VALUES (?,?)"); 
int nthPlaceholder = 1; // 1-based counting (not an index). 
preparedStatement.setObject(nthPlaceholder++, uuid); 
preparedStatement.setString(nthPlaceholder++, foodName); 
// Execute SQL. 
if (!(preparedStatement.executeUpdate() == 1)) { 
    // If the SQL reports other than one row inserted… 
    this.logger.error("Failed to insert row into database."); 
} 

(с) Я не уверен, что вы подразумеваете под

Новейшие драйверы Java JDBC для Postgres претендует на поддержку UUID, изначально

Какой драйвер? Есть как минимум два открытых драйвера JDBC для Postgres, current/legacy one и новый переписывающий "next generation" one. И есть и другие коммерческие водители.

"изначально"? Можете ли вы ссылаться на документацию, которую вы читаете? Спецификация SQL не имеет типа данных для UUID (к сожалению, ☹), поэтому JDBC spec не имеет типа данных для UUID. В качестве обходного пути драйвер JDBC для Postgres использует методы setObject и getObject на PreparedStatement, перемещая UUID через пропасть между Java ↔ SQL ↔ Postgres. См. Примерный код выше.

Как PreparedStatement JDBC doc говорит:

Если преобразование типов произвольного параметра требуется, метод SetObject следует использовать с целевым типом SQL.

Возможно, с помощью «изначально» вы смутили встроенную поддержку Postgres для UUID в качестве типа данных с JDBC, имеющим тип данных UUID. Postgres действительно поддерживает UUID в качестве типа данных, что означает, что значение хранится как 128-битное, а не многократно, если оно хранилось как шестнадцатеричная строка ASCII или Unicode. И, будучи родным, также означает, что Postgres знает, как построить индекс в столбце этого типа.

Пункт моего сообщения в блоге, упомянутый выше, состоял в том, что я был приятно удивлен тем, насколько просто преодолеть эту пропасть между Java ↔ SQL ↔ Postgres. В моих первых необразованных попытках я слишком много работал.


Еще одно замечание о Postgres поддержки UUID ... Postgres знает, как хранить, индексировать и извлекать существующие значения UUID.К сгенерируйте Значения UUID, вы должны включить расширение Postgres (плагин) uuid-ossp. Это расширение обертывает a library provided by The OSSP Project для генерации множества типов значений UUID. См. my blog for instructions.


Кстати ...

Если бы я знал, как обратиться в экспертную группу JDBC или команда JSR, чтобы JDBC в курсе UUID, я, конечно, был бы. Они делают это только для новых типов даты, определяемых в JSR 310: Date and Time API.

Аналогичным образом, если бы я знал, как просить комитет стандартов SQL, чтобы добавить тип данных UUID, я бы это сделал. Но, по-видимому, этот комитет более скрыт, чем советское Политбюро и медленнее ледника.

+5

> Этот комитет более скрыт, чем советское Политбюро и медленнее ледника. ... Комментарий года !!! –

11

Я использовал следующий подход, чтобы добавить UUID и другие объекты Postgres:

PGobject toInsertUUID = new PGobject(); 
toInsertUUID.setType("uuid"); 
toInsertUUID.setValue(uuid.toString()); 
PreparedStmt stmt = conn.prepareStatement(query); 
stmt.setObject(placeHolder,toInsertUUID); 
stmt.execute(); 

Этот путь вы будете останавливая себя делать отливку типа. Этот фрагмент кода отлично работал для меня в любое время, например, даже для json.

+1

Спасибо. Это должно быть отмечено как ответ. – azhidkov

0

попробовать

.setParameter("uuid", uuid, PostgresUUIDType.INSTANCE); 

 Смежные вопросы

  • Нет связанных вопросов^_^