programing

RAW(16) 열에 UUID를 삽입하는 방법

lastmoon 2023. 8. 5. 10:55
반응형

RAW(16) 열에 UUID를 삽입하는 방법

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가 RAW(16) 열에 UUID를 삽입하도록 하는 방법이 있습니까?

Oracle JDBC 12.2.0.1.0을 사용하고 있습니다.

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();
  }

Oracle에는 실제 UUID 데이터 유형 및 처리 방법이 없습니다.RAW(16)정말로 피타입니다.

우리가 하는 일은 UUID를 문자열로 전달하는 것입니다. UUID는 다음을 사용하는 것입니다.hextoraw():

String sql = "insert into foo (id) values (hextoraw(?))";
PreparedStatement pstmt = connection.prepareStatement(sql);
UUID uid = UUID.randomUUID();
pstmt.setString(1, uid.toString().replaceAll("-", ""));
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;
    }

JdbcTemplate 에서는 삽입과 같은 다양한 DML 작업 수행 방법을 제공합니다.예를 들어, 생각해 보세요.update.

@MarmiteBomber는 답변에서 필요한 작업을 수행하는 데 필요한 모든 정보를 제공합니다. 코드를 스프링이 정의한 다른 아티팩트에 적절히 포장하기만 하면 됩니다.

예를 들어 다음과 같은 것을 사용할 수 있습니다.

jdbcTemplate.update(new PreparedStatementCreator() {
  @Override
  public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
    PreparedStatement ps = con.prepareStatement("insert into TAB_UUID (id, uuid) values (?,?)");
    ps.setInt(1,1);
    UUID uuid = UUID.randomUUID();
    ps.setBytes(2,asBytes(uuid));
    return ps;
  }
});

람다를 사용하여 코드를 단순화하면 다음을 수행할 수 있습니다.

jdbcTemplate.update(con -> {
  PreparedStatement ps = con.prepareStatement("insert into TAB_UUID (id, uuid) values (?,?)");
  ps.setInt(1,1);
  UUID uuid = UUID.randomUUID();
  ps.setBytes(2,asBytes(uuid));
  return ps;
});

원하는 경우 다음을 대신 사용할 수 있습니다.

jdbcTemplate.update("insert into TAB_UUID (id, uuid) values (?,?)", new PreparedStatementSetter() {
  @Override
  public void setValues(PreparedStatement ps) throws SQLException {
    ps.setInt(1,1);
    UUID uuid = UUID.randomUUID();
    ps.setBytes(2, asBytes(uuid));
  }
});

다시, 코드는 람다로 단순화할 수 있습니다.

jdbcTemplate.update("insert into TAB_UUID (id, uuid) values (?,?)", ps -> {
  ps.setInt(1,1);
  UUID uuid = UUID.randomUUID();
  ps.setBytes(2, asBytes(uuid));
});

두 예 모두 명시적으로 호출합니다.setBytes기초적으로 준비된 진술서에서 그리고 사용합니다.asBytesMarmite 답변에서 나온 방법.

언급URL : https://stackoverflow.com/questions/51023782/how-to-insert-uuid-into-raw16-column

반응형