Есть ли альтернатива rawtohex для вставки данных в столбец BLOB-объектов в H2? - PullRequest
0 голосов
/ 11 июня 2018

У меня есть приложение Java, которое подключается к базе данных Oracle.Одна из таблиц содержит столбец BLOB-объектов, который мы заполняем с помощью utl_raw.cast_to_raw, например:

public class MyDAO extends JdbcDaoSupport {
    public void persist(String name, String data) {
        String sql = "insert into table (id, name, data) values " +
                     "(sequence.nextval, ?, utl_raw.cast_to_raw(?))";
        getJdbcTemplate().update(sql, [name, data]);
    }
}

По некоторым причинам, которые мне не известны, мы не используем Hibernate, JPAили что-нибудь подобное в этом приложении.Просто простые операторы SQL и Spring JDBC для их выполнения.(...) В любом случае, вышеуказанный метод работает нормально.По крайней мере, с Oracle.

Я настроил базу данных H2 в памяти с минимальным объемом данных для использования в наших тестах JUnit.Но в H2 нет пакета utl_raw. Очевидно, что путь - использовать rawtohex функцию .Это вид работ ... но это удваивает длину данных .Например, если я сохраню строку "TEST" в столбце BLOB-объектов, а затем получу ее значение, оно станет " T E S T".В качестве байтового массива это будет [0, 84, 0, 69, 0, 83, 0, 84].В документации H2 указано, что это должно произойти:

Преобразует строку в шестнадцатеричное представление.Используется 4 шестнадцатеричных символа на символ строки.

Странно .Я полагаю, что таким способом поддерживаются строки UTF-16 (?), Но я использую UTF-8.Это на самом деле повреждает моих данных.

Есть ли другой способ сохранить большой двоичный объект в H2? Я видел этот ответ, где они предлагают использоватьPreparedStatement , но тогда мне придется самому обработать соединение:

super.getConnection().prepareStatement(/* ... */).executeUpdate();
// release the statement and the connection, handle exceptions

Конечно, это не намного страшнее, чем у нас сейчас, но тем не менее, я 'Я очень неохотно изменяю рабочий производственный код только для того, чтобы сделать его совместимым с нашей тестовой установкой JUnit.

Другой вариант - получить BLOB-объект, как если бы он был строкой UTF-16, поэтому он фактически будет использовать 4 гексаза персонажа.Но опять же, я бы исправил проблему только для H2, и вместо этого решил бы ее для Oracle.

Есть ли у меня другой выбор?Можно ли как-то сказать базе данных H2 использовать только 1 байт на символ в rawtohex?Или, может быть, другая функция , которую я могу использовать вместо rawtohex?

1 Ответ

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

Я бы не стал выполнять преобразование в базе данных (Oracle или H2).

Документы H2 скажем, использовать PreparedStatement.setBinaryStream.Это может работать на Oracle тоже?В зависимости от размера конвертируемой строки, другие подходы могут быть более производительными.Кстати, есть ли какие-то конкретные причины для преобразования строк в двоичные объекты?

Если вы знаете, что это всегда относительно небольшие строки (например, <1 МБ), вы, вероятно, довольно безопасно попробовать что-то вроде этого: </p>

String sql = "insert into table (id, name, data) values " +
             "(sequence.nextval, ?, ?)";
PreparedStatement ps = super.getConnection().prepareStatement(sql);
InputStream stream = new ByteArrayInputStream(data.getBytes(StandardCharsets.UTF_8));
ps.setString(1, name);
ps.setBinaryStream(2, stream);
ps.executeUpdate();
...