Всем привет.
Случилась у меня проблема, на которую я в инете ответа не нашел.
Надеюсь что тут подскажут где искать.
Суть проблемы в том, что
ResultSet.getBytes и ResultSet.getBinaryStream возсращают разный контент ! (getBytes — неправельный, getBinaryStream — правельный)
У меня стабильно не работает на:
Oracle 10g
Oracle's thin JDBC driver for JDK 1.4
JDK 1.4.2_06
Проверочный код ниже.
Акцент на методы
getAsBytes и
getAsStream.
package dbSelect;
import java.io.*;
import java.sql.*;
import java.awt.*;
public class FromOracle {
private static Connection createConnection() throws ClassNotFoundException, SQLException {
Class.forName("oracle.jdbc.driver.OracleDriver");
return DriverManager.getConnection("jdbc:oracle:thin:@172.25.8.30:1521:ORCL", "system", "password");
}
private static void createAndFillTable() throws SQLException, ClassNotFoundException, IOException {
Connection connection = createConnection();
try {
connection.createStatement().execute("drop table test1");
} catch (SQLException e) {
// ignore if table doesn't exist
}
connection.createStatement().execute("create table test1 (attribute blob)");
PreparedStatement preparedStatement = connection.prepareStatement("insert into test1 (attribute) values (?)");
preparedStatement.setBytes( 1, toByteArray(new Point(12,34)) );
preparedStatement.execute();
connection.close();
}
private static byte[] getAsBytes() throws SQLException, ClassNotFoundException {
Connection connection = createConnection();
try {
ResultSet resultSet = connection.createStatement().executeQuery("select attribute from test1");
resultSet.next();
return resultSet.getBytes(1);
} finally {
connection.close();
}
}
private static byte[] getAsStream() throws SQLException, ClassNotFoundException, IOException {
Connection connection = createConnection();
try {
ResultSet resultSet = connection.createStatement().executeQuery("select attribute from test1");
resultSet.next();
InputStream binaryStream = resultSet.getBinaryStream(1);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
copyStreamContent(binaryStream, baos);
return baos.toByteArray();
} finally {
connection.close();
}
}
public static void main(String[] args) throws ClassNotFoundException, SQLException, IOException {
createAndFillTable();
byte[] resultAdBytes = getAsBytes();
byte[] resultAsStream = getAsStream();
System.out.println("resultAdBytes.length = " + resultAdBytes.length);
System.out.println("resultAsStream.length = " + resultAsStream.length);
System.out.println("resultAdBytes:");
printByteArray(resultAdBytes);
System.out.println("resultAsStream:");
printByteArray(resultAsStream);
System.out.println("fromByteArray(resultAsStream) = " + fromByteArray(resultAsStream));
System.out.println("fromByteArray(resultAdBytes) = " + fromByteArray(resultAdBytes));
/*
java.io.StreamCorruptedException: invalid stream header
at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:737)
at java.io.ObjectInputStream.<init>(ObjectInputStream.java:253)
. . .
*/
}
public static void printByteArray(byte[] array) {
for (int i = 0; i < array.length; i++)
System.out.print(array[i] + " ");
System.out.println();
}
public static Object fromByteArray(byte[] buf) throws IOException, ClassNotFoundException {
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(buf);
final ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
final Object result = objectInputStream.readObject();
objectInputStream.close();
return result;
}
public static byte[] toByteArray(Object original) throws IOException {
final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
final ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
objectOutputStream.writeObject(original);
objectOutputStream.close();
byte[] buf = byteArrayOutputStream.toByteArray();
return buf;
}
public static void copyStreamContent(InputStream inputStream, OutputStream outputStream) throws IOException {
final byte[] buffer = new byte[10 * 1024];
int count;
while ((count = inputStream.read(buffer)) > 0)
outputStream.write(buffer, 0, count);
}
}
результат на экране:
resultAdBytes.length = 86
resultAsStream.length = 51
resultAdBytes:
0 84 0 1 1 12 0 0 0 1 0 0 0 1 0 0 0 2 110 -87 0 0 -49 -13 0 0 -49 -14 0 1 0 1 0 0 0 1 -84
-19 0 5 115 114 0 14 106 97 118 97 0 0 119 116 0 43 111 -31 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 -49 -14 0 64 -36 -86 0 0
resultAsStream:
-84 -19 0 5 115 114 0 14 106 97 118 97 46 97 119 116 46 80 111 105 110 116 -74 -60 -118 114
52 126 -56 38 2 0 2 73 0 1 120 73 0 1 121 120 112 0 0 0 12 0 0 0 34
fromByteArray(resultAsStream) = java.awt.Point[x=12,y=34]
java.io.StreamCorruptedException: invalid stream header
at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:737)
at java.io.ObjectInputStream.<init>(ObjectInputStream.java:253)
at dbSelect.FromOracle.fromByteArray(FromOracle.java:95)
at dbSelect.FromOracle.main(FromOracle.java:77)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:324)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:86)
Exception in thread "main"
Первые четыре байта
должны быть "-84 -19 0 5", а вот в resultAdBytes — не так
Подскажите, спецы.
Здравствуйте, Pan-Halt, Вы писали:
PH> ... skipped ...
Не спец в оракловском JDBC, но когда у нас возникла похожая проблема с чтением блобов, следующий подход помог:
ResultSet rs = ...;
rs.getBlob(index).getBytes(1, (int)rs.getBlob(index).length());
Здравствуйте, investigator, Вы писали:
PH>> ... skipped ...
I>Не спец в оракловском JDBC, но когда у нас возникла похожая проблема с чтением блобов, следующий подход помог:
I>I>ResultSet rs = ...;
I>rs.getBlob(index).getBytes(1, (int)rs.getBlob(index).length());
I>
Ты прав. Такой подход работает.
Но есть одно но: вызываю getBytes не я, а hibernate... Поэтому хочеться разобраться что тут не так, а уж после hbernate карячить.
Здравствуйте, Pan-Halt, Вы писали:
PH>Здравствуйте, investigator, Вы писали:
PH>>> ... skipped ...
I>>Не спец в оракловском JDBC, но когда у нас возникла похожая проблема с чтением блобов, следующий подход помог:
I>>I>>ResultSet rs = ...;
I>>rs.getBlob(index).getBytes(1, (int)rs.getBlob(index).length());
I>>
PH>Ты прав. Такой подход работает.
PH>Но есть одно но: вызываю getBytes не я, а hibernate... Поэтому хочеться разобраться что тут не так, а уж после hbernate карячить.
Если получится хибернат раскорячить под ораклиные блобы сообщите плз о результатах
Спасибо.
Здравствуйте, Аноним, Вы писали:
I>>>Не спец в оракловском JDBC, но когда у нас возникла похожая проблема с чтением блобов, следующий подход помог:
I>>>I>>>ResultSet rs = ...;
I>>>rs.getBlob(index).getBytes(1, (int)rs.getBlob(index).length());
I>>>
PH>>Ты прав. Такой подход работает.
PH>>Но есть одно но: вызываю getBytes не я, а hibernate... Поэтому хочеться разобраться что тут не так, а уж после hbernate карячить.
А>Если получится хибернат раскорячить под ораклиные блобы сообщите плз о результатах
А>Спасибо.
Собсвенно, скорее всего Вам поможет подмена get и set методов в хибернейтовском BinaryType на то, что предложил
investigator.
Но я такой подход не пробывал и за корректность не ручаюсь.
Здравствуйте, Pan-Halt, Вы писали:
PH>Возможно, Вам поможет флажок "hibernate.jdbc.use_streams_for_binary" — "Use streams when writing/reading binary or serializable types to/from JDBC".
PH>При установке в true хибертейтовский BinaryType читает данные через потоки.
PH>А какая в Вас проблема?
в наст. момент мапинг блобов не произвожу, а делаю а в лоб через нибернатовский Connection (пока устраивает)
по поводу мапинга нашёл
статейку может кому пригодиться
Ещё раз спасибо.