Вставка и чтение больших двоичных объектов memsql

Я пытаюсь вставить большой двоичный объект в свою базу данных MemSQL.

Здесь я получаю свой источник для вставки, поэтому я конвертирую его в большой двоичный объект:

byte[] bytes = rs.getString(2).getBytes("utf-8");
Blob blob = insert.insertTableBinary(bytes);

Это моя функция insertTableBinary:

Blob blob = conn.createBlob();
blob.setBytes(1, bytes);
System.out.println(blob.length());
String sql = "INSERT INTO binaire(receipt) VALUES(\"" + blob + "\")";
executeSQL(sql);    
return blob;

На данный момент blob.lenght равен 1555, но когда я прочитал это благодаря:

String sql2 = "SELECT * FROM binaire";
Statement st = conn.createStatement();
ResultSet rs2 = st.executeQuery(sql2);
while(rs2.next()) { 
    Blob blob = rs2.getBlob(1);
    System.out.println(blob.length());
}

Длина 25. Странно то, что когда я смотрю данные в таблице, я получаю: com.mysql.jdbc.Blob@6a8bc5d9

Так это не хранит хорошую вещь, нет? Я думаю, это ссылка на объект, но не на каплю.

Но я не знаю, что я делаю неправильно, я вижу много примеров с подготовленным оператором, но эта функция недоступна в MemSQL.


person Spierki    schedule 22.07.2015    source источник


Ответы (2)


Как предположил Джозеф, лучший способ выполнить запрос — использовать подготовленные операторы JDBC. Они поддерживаются в MemSQL и являются предпочтительным способом выполнения параметризованных запросов, поскольку они делают все экранирование за вас.

Причина, по которой вы получаете свою 25-байтовую строку вместо строки, которую вставляете, заключается в том, что метод Blob toString не переопределяется в Java, и когда он неявно приводится к строке, он просто возвращает какой-то указатель Java вместо содержимого. Основываясь на моих ограниченных знаниях Java, альтернатива, которую Джозеф предложил во второй половине своего ответа (явное приведение к строке), приведет к такому же поведению. Один из способов решить эту проблему — получить массив байтов из большого двоичного объекта (blob.getBytes) и передать его в виде строки.

String sql = "INSERT INTO binaire(receipt) VALUES(\"" + new String(blob.getBytes()) + "\")";

Это, однако, очень подвержено проблемам с SQL-инъекцией (если большой двоичный объект содержит двойную кавычку, запрос либо завершится ошибкой, либо приведет к нежелательному результату), поэтому вместо этого следует использовать решение с подготовленным оператором из ответа Джозефа.

person Ishamael    schedule 22.07.2015
comment
Вроде работает спасибо. Я думал, что подготовленный оператор не работает в MemSQL, потому что он указан здесь: docs.memsql.com/latest/concepts/unsupported/ - person Spierki; 23.07.2015

редактировать: оставьте blob как byte[], если можете.

Во-первых, я настоятельно рекомендую использовать prepareStatement.

Что-то типа

PreparedStatement stmt = con.preparedStatement("INSERT INTO binaire(receipt) VALUES(?)");
stmt.setObject(1, blob)
stmt.executeUpdate()

Но если вам не нравится идея подготовленного оператора, вы можете просто сделать

String sql = "INSERT INTO binaire(receipt) VALUES(\"" + new String(blob) + "\")";

лучший, - ДжоЙо

person Joseph Victor    schedule 22.07.2015
comment
Я не ненавижу подготовленный оператор, его нет в MemSQL. Строка конструктора (Blob) тоже не существует, поэтому я не могу использовать new String(blob) . И использование blob.toString() ничего не меняет - person Spierki; 22.07.2015
comment
Я слишком быстро прочитал ваш вопрос, я подумал, что блоб - это байт []. В любом случае, con.prepareStatement — это JDBC, не так ли? MemSQL это не волнует. Просто используйте byte[] напрямую или даже String. - person Joseph Victor; 22.07.2015