Java向PostgreSQL发送prepared statement 与 libpq 向PostgreSQL发送prepared statement之比较:
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之比较:的更多相关文章
- java如何连接数据库并对其操作(以PostgreSQL为例)
java如何连接数据库并对其操作(以PostgreSQL为例) 相关概念 JDBC(Java Data Base Connectivity)是一种用于执行SQL语句的Java API,可以为多种关系数 ...
- mina的编码和解码以及断包的处理,发送自己定义协议,仿qq聊天,发送xml或json
近期一段时间以来,mina非常火,和移动开发一样.异常的火爆.前面写了几篇移动开发的文章,都还不错.你们的鼓舞就是我最大的动力.好了,废话少说.我们来看下tcp通讯吧. tcp通讯对于java来说是非 ...
- 再不了解PostgreSQL,你就晚了之PostgreSQL主从流复制部署
前言 在MySQL被收购之后,虽然有其替代品为: MariaDB,但是总感觉心里有点膈应.大家发现了另一款开源的数据库: PostgreSQL. 虽然centos自带版本9.2也可以用,但是最近的几次 ...
- dubbo发送过程编码失败,会唤醒发送线程吗?
dubbo发送过程编码失败,会唤醒发送(客户端业务)线程吗?如何实现的? 在上篇文章 dubbo坑- No provider available for the service xxx 中,如果dub ...
- PostgreSQL介绍以及如何开发框架中使用PostgreSQL数据库
最近准备下PostgreSQL数据库开发的相关知识,本文把总结的PPT内容通过博客记录分享,本随笔的主要内容是介绍PostgreSQL数据库的基础信息,以及如何在我们的开发框架中使用PostgreSQ ...
- [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 ...
- 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){ ...
- keyup实现在输入状态不发送搜索请求,停止输入后发送
个人需求:通过keyup事件配合后台elasticsearch(弹性搜索),用户在输入状态不发送请求,等停止输入后发送请求. 这是个思考笔记,因为项目临时需要弹性搜索功能,所以临时想了这么个法子,方法 ...
- Namespace declaration statement has to be the very first statement in the script-去除bom头
今天准备测试小程序的签名加密,但是刚引入官方的“加密数据解密算法”文件到项目里,然后为每个文件添加命名空间的时候,不管怎么加都报“Namespace declaration statement has ...
随机推荐
- Complete The Pattern #2
Complete The Pattern #2 Description: Task: You have to write a function pattern which creates the fo ...
- Export BOM - BOMPXINQ.EXPLODER_USEREXIT API
--======================================================================== -- Procedure : explode ...
- 解决Eclipse导出javadoc乱码问题
在Eclipse里 export 选 JavaDoc,在向导的最后一页的Extra JavaDoc Options 里填上参数即可 比如项目采用的是UTF-8的编码就填:-encoding UTF-8 ...
- poj3067
求交点的个数: 容易发现,对于两条航线(xi,yi)和(xj,yj),设xi<xj 只有yi>yj时两条航线存在交点: 于是我们考虑以x为第一关键字减序,y为第二关键字为减序排序: 则对于 ...
- ExtJs双ActionResult共用同一Js文件ID冲突解决方案
项目使用MVC+ExtJs实现,权限控制是基于Controller下的ActionResult的,有一个页面因参数不同就需要新建两个ActionResult. 不要问我为何是基于页面级,而不是数据级, ...
- Ejabberd源码解析前奏--调试
一.日志文件 一个ejabberd节点写两个日志文件: ejabberd.log ejabberd 服务日志, 由 ejabberd 节点汇报的消息erlang.log Erlang/OTP 系 ...
- Spring 教程(二)
一.Spring AOP介绍 开发其实就是在不断的重构,抽象重复代码,然后进行封装.从最原始的模块化编程到面向对象编程,代码的封装越来越整齐清晰,但是依然存在重复的代码,而这些重复代码几乎都是与业务逻 ...
- 《深入Java虚拟机学习笔记》- 第7章 类型的生命周期/对象在JVM中的生命周期
一.类型生命周期的开始 如图所示 初始化时机 所有Java虚拟机实现必须在每个类或接口首次主动使用时初始化: 以下几种情形符合主动使用的要求: 当创建某个类的新实例时(或者通过在字节码中执行new指令 ...
- HDU 5534 Partial Tree 完全背包
一棵树一共有2*(n-1)度,现在的任务就是将这些度分配到n个节点,使这n个节点的权值和最大. 思路:因为这是一棵树,所以每个节点的度数都是大于1的,所以事先给每个节点分配一度,答案 ans=f[1] ...
- 9.19AD和DA操作
下载芯片说明书的网站:http://www.21ic.com/ D/A digital是数字信号,analog是模拟信号,单片机属于数字芯片,内部只有0和1,这两种信息无法表示一个模拟量,如果是一个8 ...