通過測試:JAVA存取PostgreSQL的bytea類型均存在內存的限制問題(存取的數據過大會出現out of memory內存溢出的問題),EnterpriseDB對此作了優化。 html
取PostgreSQL中的bytea,並存儲到硬盤上. java
/** * @author Liu Yuanyuan */ private void getBytea { Connection conn = null; Statement stmt = null; ResultSet rs = null; try { String driver = "org.postgresql.Driver"; String url = "jdbc:postgresql://" + "127.0.0.1" + ":" + "5866" + "/" + "db1"; Class.forName(driver); System.out.println("find class"); conn = DriverManager.getConnection(url, "lyy", "lyy"); System.out.println("connected"); stmt = conn.createStatement(); String sql = "select obj from lyy.rawtable2 where id = 1"; rs = stmt.executeQuery(sql); System.out.println("sql=" + sql); while (rs.next()) { System.out.println(rs.getMetaData().getColumnTypeName(1)); OutputStream ops = null; InputStream ips = null; File file = new File("e:" + File.separator + 「binary」); try { ips = rs.getBinaryStream(1); byte[] buffer = new byte[ips.available()];//or other value like 1024 ops = new FileOutputStream(file); for (int i; (i = ips.read(buffer)) > 0;) { ops.write(buffer, 0, i); ops.flush(); } } catch (Exception ex) { ex.printStackTrace(System.out); } finally { ips.close(); ops.close(); } } } catch (Exception ex) { ex.printStackTrace(System.out); } finally { try { If(rs!=null) rs.close(); if(stmt!=null) stmt.close(); if(conn!=null) conn.close(); } catch (SQLException ex) { ex.printStackTrace(System.out); } } }
向bytea直接插入二進制文件 sql
Private void insertByteaByBase64() { String driver = "org.postgresql.Driver"; String url = "jdbc:postgresql://" + "127.0.0.1" + ":" + "5432" + "/" + "postgres"; Connection conn = null; PreparedStatement ps = null; ResultSet st = null; try { Class.forName(driver); System.out.println("success find class"); conn = DriverManager.getConnection(url, "postgres", "pg"); System.out.println("success connect"); String sql = "insert into blobtable(id,obj) values(?,?)"; ps = conn.prepareStatement(sql); String fpath = 「d:」+File. Separator + 「image.jpg」; File file = new File(fpath); InputStream ips = new FileInputStream(file); ps.setInt(1, 400); ps.setBinaryStream(2, ips, file.length()); ps.executeUpdate(); System.out.println("insert"); } catch (Exception ex) { ex.printStackTrace(System.out); } finally { try { if(ps!=null) ps.close(); if(conn!= null) conn.close(); } catch (SQLException ex) { ex.printStackTrace(System.out); }} }
經過base64向bytea插入二進制文件 api
Private void insertByteaByBase64() { String driver = "org.postgresql.Driver"; String url = "jdbc:postgresql://" + "127.0.0.1" + ":" + "5432" + "/" + "postgres"; Connection conn = null; PreparedStatement ps = null; ResultSet st = null; try { Class.forName(driver); System.out.println("success find class"); conn = DriverManager.getConnection(url, "postgres", "pg"); System.out.println("success connect"); byte[] b = ByteaClass.getBytes();//獲得數組byte[] System.out.println("Length = " + b.length); String s = Base64.encodeBytes(b, 0, b.length); System.out.println("s = " + s.length()); String sql = "insert into blobtable(id,obj) values(?,?)"; String c = "decode(\'" + s + "\',\'base64\')"; sql = sql.replace("?,?", "?," + c); System.out.println("sql = " + sql); ps = conn.prepareStatement(sql); ps.setInt(1, 400); ps.executeUpdate(); System.out.println("insert"); } catch (Exception ex) { ex.printStackTrace(System.out); } finally { try { if(ps!=null) ps.close(); if(conn!= null) conn.close(); } catch (SQLException ex) { ex.printStackTrace(System.out); } } }
常見錯誤1:setBinaryStream(,,int/long)參數類型異常 數組
錯誤信息:Exception in thread "Thread-3" java.lang.AbstractMethodError: org.postgresql.jdbc3g.Jdbc3gPreparedStatement.setBinaryStream(ILjava/io/InputStream;J)V app
錯誤緣由: ide
ppstmt2.setBinaryStream(k, new FileInputStream(file),file.length()); post
file.length()是long型,postgresql-9.2-1002.jdbc3.jar僅支持setBinaryStream(,,int); 測試
若不改變Jar包,能夠強制轉換爲int,ppstmt2.setBinaryStream(k, new FileInputStream(file),(int)file.length()); fetch
若不強制轉化爲int,能夠換jar包爲postgresql-9.2-1003.jdbc4.jar,該jar包支持
setBinaryStream(,,int)和setBinaryStream(,,long)
參考資料:
PostgreSQL的版本介紹和jar下載: http://jdbc.postgresql.org/download.html
JDBC3statement的介紹:
JDBC4statement的詳細介紹還沒有推出。
常見錯誤2:沒法爲preparedStatement綁定參數setBinaryStream(,,int/long)
錯誤信息:
org.postgresql.util.PSQLException: Unable to bind parameter values for statement.
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:275)
at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:555
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:417)
at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:410)
JDBC源代碼:
try { handler = sendQueryPreamble(handler, flags); sendQuery((V3Query)query, (V3ParameterList)parameters, maxRows, fetchSize, flags); sendSync(); processResults(handler, flags); } catch (PGBindException se) { // There are three causes of this error, an // invalid total Bind message length, a // BinaryStream that cannot provide the amount // of data claimed by the length arugment, and // a BinaryStream that throws an Exception // when reading. // // We simply do not send the Execute message // so we can just continue on as if nothing // has happened. Perhaps we need to // introduce an error here to force the // caller to rollback if there is a // transaction in progress? // sendSync(); processResults(handler, flags); handler.handleError(new PSQLException(GT.tr("Unable to bind parameter values for statement."), PSQLState.INVALID_PARAMETER_VALUE, se.getIOException())); }