2019独角兽企业重金招聘Python工程师标准>>>
经过测试: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);
}}
}
通过base64向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");
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())); }