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 ...
随机推荐
- android 引用 project以及下拉刷新开源类库Android-PullToRefresh 的使用
Android-PullToRefresh 是一个github上的开源下拉刷新类库, GitHub .此外,该作者还有另外一个实用度和关注量极高的项目–另一种Android ActionBar的实现 ...
- 基于Android Studio搭建hello world工程
基于Android Studio搭建hello world工程 版本:ANDROID STUDIO V0.4.6 This download includes: · Android St ...
- [转] android自动化之MonkeyRunner测试环境配置(一)
Android自动化测试之MonkeyRunner 一.Android自动化测试之环境搭建 1.1 Android-sdk介绍 ¢ SDK(Software development kit)软件开发 ...
- multiselect2side双向选择列表插件改进版
为了满足实际程序需要,特在multiselect2side插件的基础上改进已满足异步加载(如MVC)的需要.增加了加载url.saveurl属性以及控件实时刷新加载数据方法,请注意下面红色标记部分. ...
- LeetCode Product of Array Except Self (除自身外序列之积)
题意:给一个序列nums,要求返回一个序列ans,两序列元素个数相同,ans第i个元素就是除了nums[i]之外所有的数相乘之积. 思路:时间O(n),额外空间O(0). 第一次扫一遍,处理nums[ ...
- 使用powerdesigner 画图的详细说明
一.概念数据模型概述 数据模型是现实世界中数据特征的抽象.数据模型应该满足三个方面的要求: 1)能够比较真实地模拟现实世界 2)容易为人所理解 3)便于计算机实现 概念数据模型也称信息模型,它以实体- ...
- 网站资料收集 主要查看js的学习部分
1.Asp.Net MVC3.0基本的简单的可能都会用,更深入的使用还需加深研究,之后希望对MVC4.0和5.0进行对比学习,暂时看到@葡萄城控件技术团队博客的MVC5系列正在继续http://www ...
- [原创]一种简单的cocos2d-x动态更新方案
介绍一个曾经在cocos2d-x项目中使用过的动态更新方案,这个方案简单易行,针对小的项目非常有用. 这个方案有两个核心的关键词:JSON,MD5. 原理可以简单地概括为:服务端持有所有动态更新资源文 ...
- Makefile编程
[个人体会]0.1 项目文件要合理分隔,功能模块分开放,分别设置Makefile自动编译, 0.2 源码和头文件分开放,一个或多个头文件对应一个源码文件. ...
- NIOP1995 石子合并(区间DP)
状态转移方程在代码中标出 本题注意是圆形,所以之前要预先处理一下s数组.处理之后总长度为2*n-1.第一个合并的起点有n个,所以总的方案数是n 注释在代码中标出 http://www.rqnoj.cn ...