JAVA存取PostgreSQL二进制类型bytea

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

经过测试:JAVA存取PostgreSQL的bytea类型均存在内存的限制问题(存取的数据过大会出现out of memory内存溢出的问题),EnterpriseDB对此做了优化。

 取PostgreSQL中的bytea,并存储到硬盘上.

/**
 * @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直接插入二进制文件

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插入二进制文件

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

    错误原因

     ppstmt2.setBinaryStream(k, new FileInputStream(file),file.length());

file.length()是long型,postgresql-9.2-1002.jdbc3.jar仅支持setBinaryStream(,,int);

若不改变Jar包,可以强制转换为int,ppstmt2.setBinaryStream(k, new FileInputStream(file),(int)file.length());

若不强制转化为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())); } 


转载于:https://my.oschina.net/liuyuanyuangogo/blog/151490

你可能感兴趣的:(JAVA存取PostgreSQL二进制类型bytea)