9.5 服务器的Prepared Statements
PostgreSQL?服务器允许客户端编译那些希望能被重用于避免为每个sql声明的执行进行分解和计划编制的sql声明。从7.3版本开始,通过PREPARE和EXECUTE,这个功能性在SQL级是可以用的;从7.4版本开始,在协议级可用,但是作为Java开发人员来说,我们真正要用的只是PreparedStatement接口。
PostgreSQL™ provides a type
4 JDBC driver. Type 4 indicates
that the driver is written in Pure Java, and communicates in the
database system's own network protocol. Because of this, the driver
is platform independent; once compiled, the driver can be used on
any system.
| |
Note
先前的驱动程序版本用PREPARE 和EXECUTE来实现server-prepared声明,从7.3版本开始在所有的服务器版本上支持这个,但是它会在查询结果中产生透明的应用程序改变,就像丢失ResultSet元数据和更新的行数。现行的驱动程序采用V3协议标准,相当于避免了在查询结果中的这些改变,但是V3协议只有在7.4版本以后的服务器上才可以用。连接7.3的服务器或者使用V2协议廉洁7.4的服务器时,使用server-prepared声明将无效。
|
|
依据不用应用的需要,有几个方法可以启动服务器端的prepared statements。一般的方法是为PreparedStatement设置一个极限数。一个内部的计数器可以明了statement已经执行的次数,并在它到达极限数时开始使用服务器端的prepared statements。
| |
Note
服务器对服务器端的prepared statements只计划一次。这避免了重新计划每次查询的时间,但也意味着计划器不能利用查询的执行中使用的特殊参数值。从全局看,使用服务器端的prepared statements要谨慎。
|
|
例 9.3 使用服务器端prepared statement
| |
import java.sql.*;
public class ServerSidePreparedStatement
{
public static void main(String args[]) throws Exception
{
Class.forName("org.postgresql.Driver");
String url = "jdbc:postgresql://localhost:5432/test";
Connection conn = DriverManager.getConnection(url,"test","");
PreparedStatement pstmt = conn.prepareStatement("SELECT ?");
// cast to the pg extension interface
org.postgresql.PGStatement pgstmt = (org.postgresql.PGStatement)pstmt;
// on the third execution start using server side statements
pgstmt.setPrepareThreshold(3);
for (int i=1; i<=5; i++)
{
pstmt.setInt(1,i);
boolean usingServerPrepare = pgstmt.isUseServerPrepare();
ResultSet rs = pstmt.executeQuery();
rs.next();
System.out.println("Execution: "+i+", Used server side: " + usingServerPrepare + ", Result: "+rs.getInt(1));
rs.close();
}
pstmt.close();
conn.close();
}
}
|
|
第三个执行产生预想中使用服务器端prepared statement的结果。
| |
Execution: 1, Used server side: false, Result: 1
Execution: 2, Used server side: false, Result: 2
Execution: 3, Used server side: true, Result: 3
Execution: 4, Used server side: true, Result: 4
Execution: 5, Used server side: true, Result: 5
|
|
上面的例子要求程序员在假定的不理想的轻便型API中使用PostgreSQL?绝对代码。它也只为一些特大键入的特殊statement设置极限数,如果我们要使用在每个statement中使用这个极限数的话。我们来看看其他设置极限数使服务器端prepared statements可用的方法。在PreparedStatement上已经有一个恰当的层次,它是从Datasource或者URL资源建立连接的。服务器端prepared statement极限数可以在这些层次上任意设置,并作为其子连接(译者注:its children)的默认值。
| |
// pg扩展的接口
org.postgresql.PGConnection pgconn;
org.postgresql.PGStatement pgstmt;
// 设置一个 prepared statement 从这个url创建连接的极限数
String url = "jdbc:postgresql://localhost:5432/test?prepareThreshold=3";
//看连接是否从url获得正确的极限数
Connection conn = DriverManager.getConnection(url,"test","");
pgconn = (org.postgresql.PGConnection)conn;
System.out.println(pgconn.getPrepareThreshold()); // Should be 3
//看statement是否从连接中获得正确的极限数
PreparedStatement pstmt = conn.prepareStatement("SELECT ?");
pgstmt = (org.postgresql.PGStatement)pstmt;
System.out.println(pgstmt.getPrepareThreshold()); // Should be 3
//改变连接的极限数并确定新的statements获得了它
pgconn.setPrepareThreshold(5);
PreparedStatement pstmt = conn.prepareStatement("SELECT ?");
pgstmt = (org.postgresql.PGStatement)pstmt;
System.out.println(pgstmt.getPrepareThreshold()); // Should be 5
|
|