postgres conexion java postgresql jdbc blob

java - conexion - Postgresql, JDBC y BLOBs de transmisión



jdbc postgresql 9 (2)

Estoy tratando de recuperar un blob de una base de datos de postgres usando los controladores jdbc. Es demasiado grande para tenerlo en la memoria, así que quiero transmitirlo como descarga. Intenté usar el método getBinaryStream en ResultSet, pero resulta que este método realmente lo lee todo en la memoria, por lo que no funciona para archivos grandes.

Aparentemente, uno puede usar el método getBlob en el conjunto de resultados y presumiblemente obtener el flujo de entrada desde el blob e ir desde allí, pero ahí es donde me encuentro con mi problema.

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")

Ese es el código que estoy ejecutando. Cuando llega a esa última línea, arroja un error que no puedo entender ...

org.postgresql.util.PSQLException: valor incorrecto para el tipo long: xxxxxx

"xxxxxx" entonces es el contenido del archivo. Se puede imaginar que se vuelve bastante largo, pero no es realmente el punto.

Estoy atorado aqui. ¿Alguien tiene alguna idea sobre lo que está pasando? Heck, incluso tomaré métodos alternativos para transmitir grandes blobs como descarga.



Mi conjetura es que ha mezclado blobs estilo OID y BYTEA. Los objetos binarios grandes se almacenan indirectamente con columnas OID en Postgres. Postgres almacena los datos reales del archivo en algún lugar fuera de la tabla de la base de datos. La columna solo contiene un identificador de objeto que está asociado internamente con el blob. Por ejemplo:

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

Si usa el método ResultSet#getBlob(String) , se espera una columna de estilo OID. getBlob lee los datos de la columna y los convierte a Long . Luego intenta leer los datos binarios asociados desde su almacenamiento interno.

Por otro lado, con BYTEA puede colocar pequeños fragmentos de datos binarios directamente en su base de datos. Por ejemplo:

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)

Aquí, la columna de datos contiene directamente los datos binarios. Si intenta utilizar getBlob en una columna de este tipo, los datos se seguirán interpretando como un OID, pero obviamente no se ajustarán a un Long . Probemos esto en la base de datos, acabamos de crear:

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"); ===> org.postgresql.jdbc4.Jdbc4Connection@3a0b2c64 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() ===> org.postgresql.jdbc4.Jdbc4ResultSet@66f9104a 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) ...