JAVA存取PostgreSQL二進制類型bytea

 

通過測試: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);

            }}
}


經過base64bytea插入二進制文件 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的介紹:

http://jdbc.postgresql.org/development/privateapi/org/postgresql/jdbc3/AbstractJdbc3Statement.html#setBinaryStream(java.lang.String, java.io.InputStream, int)

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源代碼:

http://www.java2s.com/Open-Source/Java/Database-JDBC-Connection-Pool/postgresql/org/postgresql/core/v3/QueryExecutorImpl.java.htm

 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())); } 
相關文章
相關標籤/搜索