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. JSP JSP工作原理 JSP语法 JSP声明 JSP注释 JSP指令 jsp九大隐式/内置对象

    1 什么是JSP   1)为什么说,Servlet是一个动态Web开发技术呢?     Servlet是基于服务端的一种动态交互技术,     HttpServletRequest表示客户端到服务端的 ...

  2. Linux下安装Wine运行windows程序

    资料 首页 https://www.winehq.org/ 安装 https://www.winehq.org/download/ 教程 https://www.winehq.org/document ...

  3. Android 内存管理(二)

    很多开发者都是从j2me或j2ee上过来的,对于内存的使用和理解并不是很到位,Android开发网本次给大家一些架构上的指导,防止出现豆腐渣工 程的出现.Android作为以Java语言为主的智能平台 ...

  4. UVa 10214 (莫比乌斯反演 or 欧拉函数) Trees in a Wood.

    题意: 这道题和POJ 3090很相似,求|x|≤a,|y|≤b 中站在原点可见的整点的个数K,所有的整点个数为N(除去原点),求K/N 分析: 坐标轴上有四个可见的点,因为每个象限可见的点数都是一样 ...

  5. 你真的精通Java吗?

    简历和自我介绍上经常能够读到“精通Java”这样的话,有人和我说,精通Java的人太多了,精通Java已经不能算亮点.不能给自己加分了.可是事实真是这样吗? 对于语言的学习,我有一种观点,一是纵向,即 ...

  6. Java [leetcode 24]Swap Nodes in Pairs

    题目描述: Given a linked list, swap every two adjacent nodes and return its head. For example, Given 1-& ...

  7. static用法详解

    一. 面向过程程序设计 1.静态全局变量 在全局变量前,加上关键字static,该变量就被定义成为一个静态全局变量.我们先举一个静态全局变量的例子,如下: //Example 1 #include & ...

  8. MEF技术

    MEF 是一个使开发人员能够创建“插件式应用程序”的技术,这里的“插件”是指在应用程序部署后开发人员能够通过开发“插件”来扩展应用程序功能.但不同之处是使用MEF框架您在系统设计阶段不需要考虑在应用程 ...

  9. case中定义变量

    1.c语言switch/case中定义变量   case 0: int b = 0 ; printf("0");break; case 1: printf("1" ...

  10. STM32之CAN ---CAN ID过滤器分析

      1 前言 在CAN协议里,报文的标识符不代表节点的地址,而是跟报文的内容相关的.因此,发送者以广播的形式把报文发送给所有的接收者.节点在接收报文时,根据标识符(CAN ID)的值决定软件是否需要该 ...