OracleJDBC:如何将UUID插入原始(16)列

OracleJDBC:如何将UUID插入原始(16)列,oracle,jdbc,uuid,dbsetup,Oracle,Jdbc,Uuid,Dbsetup,我在Oracle中有RAW(16)PK列,并尝试使用JDBC插入其中: PreparedStatement stmt = connection.prepareStatement("insert into COUNTRY (id, state, version, code, name, nationality, issuing_entity, country) values (?, ?, ?, ?, ?, ?, ?, ?)"); UUID id = UUID.ran

我在Oracle中有RAW(16)PK列,并尝试使用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插入原始(16)列


我使用的是Oracle JDBC 12.2.0.1.0。

Oracle没有真正的UUID数据类型,处理
RAW(16)
实际上是一个PITA

我们要做的是将UUID作为字符串传递给使用
hextoraw()
的SQL语句:


必须将UUID转换为字节数组。请参阅如何执行此操作的方法

在它之后,绑定就像使用
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();
  }
这里有一个将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()
?您必须向JDBC驱动程序传递类似byte[]的内容才能允许存储数据类型RAW.id.toString()?变成生的(16)?但是怎么写呢?@ibre5041,我可以把它写成字节,但我需要让DbSetup工作起来。Hibernate很好用setBytes()代替setObject()怎么样?@Serge不客气;无论如何,根据我的经验,只有在有两个很好的理由的情况下,我才会使用/允许使用散列代码作为PK,即为什么不能使用
序列
,并且散列代码相对于数字PK具有真正的优势。祝你好运我之所以使用它,是因为需要将来自中间服务器的数据合并到主服务器上。我认为这种方法比为每个服务器维护单独的序列值范围要好。
getJdbcTemplate().update("INSERT INTO abc(abc_id, abc_uuid, "
                                       + "VALUES (?, ?)",
                                          abcId, uuidToBytes(abcUuid))
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;
    }