У меня есть столбец RAW (16) PK в Oracle, и я пытаюсь вставить в него с помощью JDBC:
PreparedStatement stmt = connection.prepareStatement("insert into COUNTRY (id, state, version, code, name, nationality, issuing_entity, country) values (?, ?, ?, ?, ?, ?, ?, ?)");
UUID id = UUID.randomUUID();
stmt.setObject(1, id, Types.BINARY);
Однако я получаю исключение:
java.sql.SQLException: Invalid column type
at oracle.jdbc.driver.OraclePreparedStatement.setObjectCritical(OraclePreparedStatement.java:8494)
at oracle.jdbc.driver.OraclePreparedStatement.setObjectInternal(OraclePreparedStatement.java:7995)
at oracle.jdbc.driver.OraclePreparedStatement.setObject(OraclePreparedStatement.java:8559)
at oracle.jdbc.driver.OraclePreparedStatementWrapper.setObject(OraclePreparedStatementWrapper.java:225)
at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.setObject(HikariProxyPreparedStatement.java)
at rw.gov.dgie.framework.test.AbstractTestCaseWithDB.tryToInsertCountry(AbstractTestCaseWithDB.java:78)
at rw.gov.dgie.framework.test.AbstractTestCaseWithDB.dbSetup(AbstractTestCaseWithDB.java:62)
at test.rw.gov.dgie.bms.terr.service.TestCountryService.init(TestCountryService.java:37)
Я получаю такое же исключение при попытке использовать DbSetup для вставки тестовых данных.
Есть ли способ заставить JDBC вставлять UUID в столбец RAW (16)?
Я использую Oracle JDBC 12.2.0.1.0.
imho вам нужно передать что-то вроде byte [] драйверу JDBC, чтобы разрешить хранение типа данных RAW.
id.toString ()? В RAW (16)? Но как?
@ ibre5041, я могу записать это в байтах, но мне нужно, чтобы DbSetup работал. Hibernate отлично работает
как насчет использования setBytes () вместо setObject ()?
setBytes () работает, но не для DbSetup





Oracle не имеет реального типа данных UUID, и работа с RAW(16) на самом деле является PITA.
Что мы делаем, так это передаем UUID в виде строки в инструкцию SQL, которая использует hextoraw():
String sql = "insert into foo (id) values (hextoraw(?))";
PreparedStatement pstmt = connection.prepareStatement(sql);
UUID uid = UUID.randomUUID();
pstmt.setString(1, uid.toString().replaceAll("-", ""));
Вы должны преобразовать UUID в байтовый массив. Смотрите метод asBytes, как это сделать.
После этого привязка осуществляется очень просто, как с помощью setBytes.
Пример
def stmt = con.prepareStatement("insert into TAB_UUID (id, uuid) values (?,?)")
// bind
stmt.setInt(1,1)
def uuid = UUID.randomUUID()
stmt.setBytes(2,asBytes(uuid))
def rowCount = stmt.executeUpdate()
Вот на всякий случай ссылка не работает метод преобразования UUID в байтовый массив
public static byte[] asBytes(UUID uuid) {
ByteBuffer bb = ByteBuffer.wrap(new byte[16]);
bb.putLong(uuid.getMostSignificantBits());
bb.putLong(uuid.getLeastSignificantBits());
return bb.array();
}
@Serge, пожалуйста; в любом случае, исходя из моего опыта, я бы использовал / разрешил использовать хэш-коды в качестве PK, только если есть две веские причины: почему sequence нельзя использовать, и этот хеш-код дает реальное преимущество перед числовым PK. Удачи!
Я использую его из-за необходимости слияния данных с промежуточных серверов на основном. Я думаю, что этот способ лучше, чем сохранение отдельного диапазона значений последовательности для каждого сервера.
getJdbcTemplate().update("INSERT INTO abc(abc_id, abc_uuid, "
+ "VALUES (?, ?)",
abcId, uuidToBytes(abcUuid))
Вот вспомогательный метод для преобразования типа UUID в байты.
private byte[] uuidToBytes(final UUID uuid) {
if (Objects.isNull(uuid)) {
return null;
}
final byte[] uuidAsBytes = new byte[16];
ByteBuffer.wrap(uuidAsBytes)
.order(ByteOrder.BIG_ENDIAN)
.putLong(uuid.getMostSignificantBits())
.putLong(uuid.getLeastSignificantBits());
return uuidAsBytes;
}
Вы не можете спасти
id.toString()?