Oracle JDBC: как вставить UUID в столбец RAW (16) - PullRequest
0 голосов
/ 25 июня 2018

У меня есть столбец 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.

Ответы [ 3 ]

0 голосов
/ 25 июня 2018

Вы должны преобразовать 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();
  }
0 голосов
/ 10 июня 2019
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;
    }
0 голосов
/ 25 июня 2018

У 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("-", ""));
...