2010-01-15 2 views
19

Я пытаюсь извлечь blob из базы данных postgres с помощью драйверов jdbc. Он слишком велик, чтобы иметь в памяти, поэтому я хочу передать его как загрузку. Я попытался использовать метод getBinaryStream на ResultSet, но, оказывается, этот метод действительно читает все это в памяти, поэтому не работает для большого файла.Postgresql, JDBC и потоковые BLOB

По-видимому, можно использовать метод getBlob на наборе результатов и предположительно получить входной поток от блоба и перейти оттуда, но именно там я столкнулся с проблемой.

PreparedStatement ps = con.prepareStatement("select data from file_data WHERE ID = ?"); 
ps.setLong(1,file.fileData.id) 
ResultSet rs = ps.executeQuery() 
if(rs.next()){ 
     rs.getBlob("data") 

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

org.postgresql.util.PSQLException: Bad значение типа Long: хххххх

«XXXXXX "то есть содержимое файла. Вы можете себе представить, что это довольно длительное время, но на самом деле это не так.

Я застрял здесь. Кто-нибудь есть идеи о том, что происходит? Черт, я даже возьму альтернативные методы для потоковой передачи больших капель в качестве загрузки.

+0

В моем случае это было 'rs.getBlob (...)' вместо 'rs.getBinaryStream (...)'. Никогда не поздно учиться JDBC. –

ответ

17

Моя догадка заключается в том, что вы смешались с блоками OID и BYTEA. Большие двоичные объекты хранятся косвенно с столбцами OID в Postgres. Фактические данные файла хранятся где-то за пределами таблицы базы данных Postgres. В столбце содержится только идентификатор объекта, связанный внутри с блобом. Например:

janko=# CREATE TABLE blobtest1 (name CHAR(30), image OID); 
CREATE TABLE            
janko=# INSERT INTO blobtest1 VALUES ('stackoverflow', lo_import('/tmp/stackoverflow-logo.png')); 
INSERT 0 1 
janko=# SELECT * FROM blobtest1; 
       name    | image 
--------------------------------+------- 
stackoverflow     | 16389 
(1 row) 

Если вы используете метод ResultSet#getBlob(String), чем OID столбец стиля, как ожидается. getBlob считывает данные из столбца и преобразует их в Long. Затем он пытается прочитать связанные двоичные данные из своего внутреннего хранилища.

С другой стороны, с BYTEA вы можете разместить небольшие кусочки двоичных данных непосредственно в своей БД. Например:

janko=# CREATE TABLE blobtest2 (name CHAR(30), image BYTEA); 
CREATE TABLE 
janko=# INSERT INTO blobtest2 VALUES ('somebinary', E'\\336\\255\\276\\357\\336\\255\\276\\357'); 
INSERT 0 1 
janko=# SELECT * FROM blobtest2; 
       name    |    image 
--------------------------------+---------------------------------- 
somebinary      | \336\255\276\357\336\255\276\357 
(1 row) 

Здесь столбец данных содержит двоичные данные. Если вы попытаетесь использовать getBlob на таком столбце, данные по-прежнему будут интерпретироваться как OID, но, очевидно, он не будет вписываться в Long. Давайте попробуем это в базе данных, мы только что создали:

groovy:000> import java.sql.* 
===> [import java.sql.*] 
groovy:000> Class.forName("org.postgresql.Driver"); 
===> class org.postgresql.Driver 
groovy:000> db = DriverManager.getConnection("jdbc:postgresql:janko", "janko", "qwertz"); 
===> [email protected] 
groovy:000> ps = db.prepareStatement("SELECT image FROM blobtest2 WHERE name = ?"); 
===> SELECT image FROM blobtest2 WHERE name = ? 
groovy:000> ps.setString(1, "somebinary") 
===> null 
groovy:000> rs = ps.executeQuery() 
===> [email protected] 
groovy:000> rs.next() 
===> true 
groovy:000> rs.getBlob("image") 
ERROR org.postgresql.util.PSQLException: Bad value for type long : \336\255\276\357\336\255\276\357 
     at org.postgresql.jdbc2.AbstractJdbc2ResultSet.toLong (AbstractJdbc2ResultSet.java:2796) 
     at org.postgresql.jdbc2.AbstractJdbc2ResultSet.getLong (AbstractJdbc2ResultSet.java:2019) 
     at org.postgresql.jdbc4.Jdbc4ResultSet.getBlob (Jdbc4ResultSet.java:52) 
     at org.postgresql.jdbc2.AbstractJdbc2ResultSet.getBlob (AbstractJdbc2ResultSet.java:335) 
     at groovysh_evaluate.run (groovysh_evaluate:3) 
     ... 
+0

Спасибо! Итак, rs.getBytes («образ») работал для меня, чтобы получить byteArray :-) – Bohne

Смежные вопросы