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. request对象常用API 获取请求参数的值 request应用 MVC设计模式

    1 request对象常用API   1)表示web浏览器向web服务端的请求   2)url表示访问web应用的完整路径:http://localhost:8080/day06/Demo1     ...

  2. Descending Order

    Descending Order Description: Your task is to make a function that can take any non-negative integer ...

  3. Android开发之MediaPlayer和SurfaceView组成视频播放器

    SurfaceView 使用双缓冲技术 是个重量级的组件 只要不可见,就不会创建,可见时,才会创建 只要不可见,就会销毁 SurfaceView一旦不可见,就会被销毁,一旦可见,就会被创建,销毁时停止 ...

  4. poj 2195 Going Home(最小费用最大流)

    题目:http://poj.org/problem?id=2195 有若干个人和若干个房子在一个给定网格中,每人走一个都要一定花费,每个房子只能容纳一人,现要求让所有人进入房子,且总花费最小. 构造一 ...

  5. Innodb parent table open时导致crash

    case描述: innodb中,父表和子表通过foreign constraint进行关联, 因为在更新数据时需要check 外键constraint,如果父表被大量的子表reference, 那么在 ...

  6. Fody

    Fody  https://github.com/Fody/Fody/ 有空还要看下怎么实现的.

  7. hdu4177:Super Mario

    主席树+离散化.给一段区间.多次询问[l,r]中有多少个数小于k.啊主席树用指针版写出来优美多了QAQ... #include<cstdio> #include<cstring> ...

  8. 分享10个Js的小型库,效果真的很棒

    1.$fx()简介:$fx()是一个轻量级的动画库,一些复杂的动画,可以由多个简单的动画效果进行组合,但是提供的是混淆压缩过的代码,对于研究动画源码的朋友可能特别不爽API:http://fx.ine ...

  9. ssh-keygen+ssh-copy-id 在linux下实现ssh无密码登录访问

    环境: 192.168.2.10 192.168.2.11 实现:2.10 ssh无需密码登录到2.11 在2.10 ssh到2.11机器上,需要密码,这样对一些脚本工作不方便,因为需要密码,也就是需 ...

  10. 【Web前沿技术】纯 CSS3 打造的10个精美加载进度条动画

    之前向大家介绍8款优秀的 jQuery 加载动画和进度条插件,今天这篇文章向大家推荐10个纯 CSS3 代码实现精美加载进度条动画效果的方案.加载动画和进度条在网站和 Web 应用中的使用非常流行,特 ...