Java 代码,在数据库端,并没有当成 prepared statetment 被处理。

C代码通过libpq 访问数据库端,被当成了 prepared statement 处理。也许是因PostgreSQL对JDBC的支持毕竟是后期出现的:

下面看代码和运行结果:

Java 代码:

import java.sql.*;

public class Test01 {

        public static void main(String argsv[]){
try
{
Class.forName("org.postgresql.Driver").newInstance();
String url = "jdbc:postgresql://localhost:5432/postgres" ; Connection con = DriverManager.getConnection(url,"postgres","postgres" ); ///Phase 1:-------------Select data from table----------------------- System.out.println("Phase 1------------------------start"); String strsql = " select * from customers where cust_id = ?";
PreparedStatement pst=con.prepareStatement(strsql); pst.setInt(,); //find the customer with cust_id of 3. ResultSet rs = pst.executeQuery(); while (rs.next())
{
System.out.print("cust_id:"+rs.getInt( "cust_id"));
System.out.println("...cust_name:"+rs.getString( "cust_name" ));
}
System.out.println("Phase 1------------------------end\n"); ///Phase 2:-------------Use connection again,to select data from data dictionary----------------------- System.out.println("Phase 2------------------------start"); strsql = "select * from pg_prepared_statements";
pst=con.prepareStatement(strsql); rs = pst.executeQuery(); while (rs.next())
{
System.out.println("statement:"+rs.getString( "statement"));
}
System.out.println("Phase 2------------------------end\n"); ///Phase 3:-------------Use connection again,to select data from table----------------------- System.out.println("Phase 3------------------------start");
strsql = "select * from customers";
pst=con.prepareStatement(strsql); rs = pst.executeQuery(); while (rs.next())
{
System.out.print("cust_id:"+rs.getInt( "cust_id"));
System.out.println("...cust_name:"+rs.getString( "cust_name" ));
} System.out.println("Phase 3------------------------end\n"); rs.close();
pst.close();
con.close(); }
catch (Exception ee)
{
System.out.print(ee.getMessage());
}
} }

运行:

Phase ------------------------start
cust_id:...cust_name:Taylor
Phase ------------------------end Phase ------------------------start
Phase ------------------------end Phase ------------------------start
cust_id:...cust_name:Smith
cust_id:...cust_name:Brown
cust_id:...cust_name:Taylor
Phase ------------------------end

C 代码:

[root@lex tst]# cat testprepared.c
/*
* testlibpq.c
* Test the C version of LIBPQ, the POSTGRES frontend library.
*/
#include <stdio.h>
#include <stdlib.h>
#include "libpq-fe.h" static void
exit_nicely(PGconn *conn)
{
PQfinish(conn);
exit(EXIT_SUCCESS);
} int
main()
{
int nFields;
int i,
j; #ifdef DEBUG
FILE *debug;
#endif /* DEBUG */ ///////////////////////////////////////////////////////////////////////////////
///Step1: making connection PGconn *conn;
PGresult *res; const char *conninfo="postgresql://postgres:postgres@localhost:5432/postgres"; /* make a connection to the database */
conn = PQconnectdb(conninfo); /* check to see that the backend connection was successfully made */
if (PQstatus(conn) == CONNECTION_BAD)
{
fprintf(stderr, "Connection to database failed.\n");
fprintf(stderr, "%s", PQerrorMessage(conn));
exit_nicely(conn);
} #ifdef DEBUG
debug = fopen("/tmp/trace.out", "w");
PQtrace(conn, debug);
#endif /* DEBUG */ ////////////////////////////////////////////////////////////////////////////////////
///Step 2, activating prepared statement /* start a transaction block */
res = PQexec(conn, "BEGIN");
if (PQresultStatus(res) != PGRES_COMMAND_OK)
{
fprintf(stderr, "BEGIN command failed\n");
PQclear(res);
exit_nicely(conn);
} PQclear(res); ////////////////////////////////////////////////////////////////////////////////////
///Step 2, activating prepared statement
const char *stmt_name = "test_stmt";
const char *stmt = "select * from customers where cust_id=$1"; Oid param_types[];
param_types[] = ; ///let db to judge it. res = PQprepare(conn, stmt_name, stmt,,param_types);
if (PQresultStatus(res) != PGRES_COMMAND_OK)
{
fprintf(stderr, "PQprepare failed\n");
PQclear(res);
exit_nicely(conn);
} PQclear(res); const char* custid = "";
const char* param_values[];
param_values[] =custid; int param_lengths[];
param_lengths[] = ; int param_formats[];
param_formats[] = ; res = PQexecPrepared(conn, stmt_name, , param_values, param_lengths,
param_formats, ); if (PQresultStatus(res) != PGRES_TUPLES_OK)
{
fprintf(stderr, "PQexecPrepared statement didn't return tuples properly\n");
PQclear(res);
exit_nicely(conn);
} /* print out the attribute names */
nFields = PQnfields(res);
for (i = ; i < nFields; i++)
printf("%-15s", PQfname(res, i)); printf("\n\n"); /* print out the instances */
for (i = ; i < PQntuples(res); i++)
{
for (j = ; j < nFields; j++)
printf("%-15s", PQgetvalue(res, i, j));
printf("\n");
} PQclear(res); /* end the transaction */
res = PQexec(conn, "END");
PQclear(res); ////////////////////////////////////////////////////////////////////////////////////
///Step 3, looking for cached status of prepared statements /* start a transaction block */
res = PQexec(conn, "BEGIN");
if (PQresultStatus(res) != PGRES_COMMAND_OK)
{
fprintf(stderr, "BEGIN command failed\n");
PQclear(res);
exit_nicely(conn);
} PQclear(res); /* define cursor */
res = PQexec(conn, "DECLARE myportal CURSOR FOR select * from pg_prepared_statements");
if (PQresultStatus(res) != PGRES_COMMAND_OK)
{
fprintf(stderr, "DECLARE CURSOR command failed\n");
PQclear(res);
exit_nicely(conn);
}
PQclear(res); /* fetch cursor */
res = PQexec(conn, "FETCH ALL in myportal");
if (PQresultStatus(res) != PGRES_TUPLES_OK)
{
fprintf(stderr, "FETCH ALL command didn't return tuples properly\n");
PQclear(res);
exit_nicely(conn);
} /* first, print out the attribute names */
nFields = PQnfields(res);
for (i = ; i < nFields; i++)
printf("%-15s", PQfname(res, i)); printf("\n\n"); /* next, print out the instances */
for (i = ; i < PQntuples(res); i++)
{
for (j = ; j < nFields; j++)
printf("%-15s", PQgetvalue(res, i, j));
printf("\n");
} PQclear(res); /* close the portal */
res = PQexec(conn, "CLOSE myportal");
PQclear(res); /* end the transaction */
res = PQexec(conn, "END");
PQclear(res); ////////////////////////////////////////////////////////////////////////////////////
///Step 4, close the connection /* close the connection to the database and cleanup */
PQfinish(conn); #ifdef DEBUG
fclose(debug);
#endif /* DEBUG */ return ;
}
[root@lex tst]#

编译与运行:

[root@lex tst]# gcc -c -I/usr/local/pgsql/include testprepared.c
[root@lex tst]# gcc -o testprepared testprepared.o -L/usr/local/pgsql/lib -lpq
[root@lex tst]# ./testprepared
cust_id cust_name 3 Taylor
name statement                 prepare_time       parameter_typesfrom_sql test_stmt select * from customers where cust_id=$ 12013-06-17 16:28:31.70059+08{integer} f

追记:

为了解决Java中处理prepared statement 的问题。在Postgresql社区提问,得到的回答是:

采用threadshold:这个算是PostgreSQL自己的扩展。修改代码如下:

[root@lex src]# cat Test01.java
import java.sql.*; public class Test01 { public static void main(String argsv[]) {
try {
Class.forName("org.postgresql.Driver").newInstance();
String url = "jdbc:postgresql://localhost:5432/postgres"; Connection con = DriverManager.getConnection(url, "postgres",
"postgres"); // /Phase 1:-------------Select data from
// table----------------------- System.out.println("Phase 1------------------------start"); String strsql = " select * from customers where cust_id = ?";
PreparedStatement pst = con.prepareStatement(strsql); org.postgresql.PGStatement pgt = (org.postgresql.PGStatement)pst; pgt.setPrepareThreshold(1); pst.setInt(1, 3); // find the customer with cust_id of 3. ResultSet rs = pst.executeQuery(); while (rs.next()) {
System.out.print("cust_id:" + rs.getInt("cust_id"));
System.out.println("...cust_name:" + rs.getString("cust_name"));
}
System.out.println("Phase 1------------------------end\n"); // /Phase 2:-------------Use connection again,to select data from
// data dictionary----------------------- System.out.println("Phase 2------------------------start"); strsql = "select * from pg_prepared_statements";
pst = con.prepareStatement(strsql); rs = pst.executeQuery(); while (rs.next()) {
System.out.println("statement:" + rs.getString("statement"));
}
System.out.println("Phase 2------------------------end\n"); // /Phase 3:-------------Use connection again,to select data from
// table----------------------- System.out.println("Phase 3------------------------start");
strsql = "select * from customers";
pst = con.prepareStatement(strsql); rs = pst.executeQuery(); while (rs.next()) {
System.out.print("cust_id:" + rs.getInt("cust_id"));
System.out.println("...cust_name:" + rs.getString("cust_name"));
} System.out.println("Phase 3------------------------end\n"); rs.close();
pst.close();
con.close(); } catch (Exception ee) {
System.out.print(ee.getMessage());
}
} }
[root@lex src]#

因为加入了这两句:

org.postgresql.PGStatement pgt = (org.postgresql.PGStatement)pst;

pgt.setPrepareThreshold(1);

所以,得到的运行结果不同了:

Phase 1------------------------start
cust_id:3...cust_name:Taylor
Phase 1------------------------end Phase 2------------------------start
statement: select * from customers where cust_id = $1
Phase 2------------------------end Phase 3------------------------start
cust_id:1...cust_name:Smith
cust_id:2...cust_name:Brown
cust_id:3...cust_name:Taylor
Phase 3------------------------end

不过,这么作的目的是什么呢,还是很让人困惑的。

http://jdbc.postgresql.org/documentation/head/server-prepare.html

The PostgreSQL™ server allows clients to compile sql statements that are expected to be reused to avoid the overhead of parsing and planning the statement for every execution. This functionality is available at the SQL level via PREPARE and EXECUTE beginning with server version 7.3, and at the protocol level beginning with server version 7.4, but as Java developers we really just want to use the standard PreparedStatement interface.
There are a number of ways to enable server side prepared statements depending on your application's needs. The general method is to set a threshold for a PreparedStatement. An internal counter keeps track of how many times the statement has been executed and when it reaches the threshold it will start to use server side prepared statements.

这里面最令我困惑的是这句话:

The PostgreSQL™ server allows clients to compile sql statements that are expected to be reused to avoid the overhead of parsing and planning the statement for every execution.

...server allows client to compile sql statements

Java向PostgreSQL发送prepared statement 与 libpq 向PostgreSQL发送prepared statement之比较:的更多相关文章

  1. java如何连接数据库并对其操作(以PostgreSQL为例)

    java如何连接数据库并对其操作(以PostgreSQL为例) 相关概念 JDBC(Java Data Base Connectivity)是一种用于执行SQL语句的Java API,可以为多种关系数 ...

  2. mina的编码和解码以及断包的处理,发送自己定义协议,仿qq聊天,发送xml或json

    近期一段时间以来,mina非常火,和移动开发一样.异常的火爆.前面写了几篇移动开发的文章,都还不错.你们的鼓舞就是我最大的动力.好了,废话少说.我们来看下tcp通讯吧. tcp通讯对于java来说是非 ...

  3. 再不了解PostgreSQL,你就晚了之PostgreSQL主从流复制部署

    前言 在MySQL被收购之后,虽然有其替代品为: MariaDB,但是总感觉心里有点膈应.大家发现了另一款开源的数据库: PostgreSQL. 虽然centos自带版本9.2也可以用,但是最近的几次 ...

  4. dubbo发送过程编码失败,会唤醒发送线程吗?

    dubbo发送过程编码失败,会唤醒发送(客户端业务)线程吗?如何实现的? 在上篇文章 dubbo坑- No provider available for the service xxx 中,如果dub ...

  5. PostgreSQL介绍以及如何开发框架中使用PostgreSQL数据库

    最近准备下PostgreSQL数据库开发的相关知识,本文把总结的PPT内容通过博客记录分享,本随笔的主要内容是介绍PostgreSQL数据库的基础信息,以及如何在我们的开发框架中使用PostgreSQ ...

  6. [MySQL复制异常]'Cannot execute statement: impossible to write to binary log since statement is in row format and BINLOG_FORMAT = STATEMENT.'

    MySQL复制错误]Last_Errno: 1666 Last_Error: Error executing row event: 'Cannot execute statement: imposs ...

  7. error: a label can only be part of a statement and a declaration is not a statement

    GCC: error: a label can only be part of a statement and a declaration is not a statement switch(a){ ...

  8. keyup实现在输入状态不发送搜索请求,停止输入后发送

    个人需求:通过keyup事件配合后台elasticsearch(弹性搜索),用户在输入状态不发送请求,等停止输入后发送请求. 这是个思考笔记,因为项目临时需要弹性搜索功能,所以临时想了这么个法子,方法 ...

  9. Namespace declaration statement has to be the very first statement in the script-去除bom头

    今天准备测试小程序的签名加密,但是刚引入官方的“加密数据解密算法”文件到项目里,然后为每个文件添加命名空间的时候,不管怎么加都报“Namespace declaration statement has ...

随机推荐

  1. Linux配置vpn

    配置如下

  2. DOCTYPE, HTML和XHTML, Strict DTD和Transitional DTD, Quirks Mode和Standard Mode

    在HTML里面声明DOCTYPE一般会有以下几种: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" ...

  3. 【HDOJ】4775 Infinite Go

    其实是一道模拟题,并查集用来优化.还可以的一道题目. /* 4775 */ #include <iostream> #include <sstream> #include &l ...

  4. Java多线程性能优化

    大家使用多线程无非是为了提高性能,但如果多线程使用不当,不但性能提升不明显,而且会使得资源消耗更大.下面列举一下可能会造成多线程性能问题的点: 死锁 过多串行化 过多锁竞争 切换上下文 内存同步 下面 ...

  5. C# Process.Kill() 拒绝访问(Access Denied) 的解决方案

    需求:很多时候我们需要后台运行几个Console来不停的计算数据,那么部署到客户服务器后,如果出现突发异常,程序挂掉了,那...? 解决方案:封装了一个对后台运行程序不停监测的功能,如果发现程序有异常 ...

  6. BZOJ_2434_[NOI2011]_阿狸的打字机_(AC自动机+dfs序+树状数组)

    描述 http://www.lydsy.com/JudgeOnline/problem.php?id=2434 给出\(n\)个字符串,\(m\)个询问,对于第\(i\)个询问,求第\(x_i\)个字 ...

  7. 了解AngularJS $resource

    原文: https://learnable.com/books/angularjs-novice-to-ninja/preview/understanding-angularjs-resource-e ...

  8. 在Azure HDInsight HBase集群中使用Thrift接口

    Sun wei  Wed, Feb 25 2015 2:17 AM Apache Thrift 是一种可扩展的跨语言服务接口,可以通过内置的代码生成引擎帮助创建跨语言服务类库,Apache HBase ...

  9. jquery自动生成分页控件 - pagetest.js

    /* pagenum:当前页数 theallnum:总条数 themeiye:每页显示多少条 */ function pagetest(pagenum, theallnum, themeiye) { ...

  10. 单点登录技术:微软Passport单点登录协议和自由联盟规范

    随着互联网络应用的普及,越来越多的人开始使用互联网上提供的服务.然而目前提供服务的网站大多采用用户名.口令的方式来识别用户身份,这使得用户需要经常性的输入自己的用户名.口令.显然这种认证方式存在着弊端 ...