自己动手写JDBC驱动来监视SQL语句(2)
2011-02-11 15:50
531 查看
Author 正正 Date 2011.01.28 13:22:00 转载请注明出处 正正博客 http://www.2009fly.com
还从没有写过连载的文章,但是上次说的不是很完整,那天晚上把人困的不行,今天补过来。晚上就要回家了,一星期不能上网,这应该是春节前的最后一篇吧。
前面我们已经有了自己的JDBC的驱动MyDriver和与数据库的连接对象MyConnection。因为连接数据库是要和底层打交道的,必须主
动的去关闭与数据库的连接,因此千万认真的实现这几个资源的close方
法:Connection,Statenment,PreparedStatement,ResultSet等。好了,切入正题,我们今天讨论一下
PreparedStatement的写法,因为其是Statement的子对象,会了PreparedStatement的书写,那么
Statement也就不在话下了。
首先,和前面介绍的思想一下,要有一个真正干活的家伙:realPreparedStatement来作为我们自己的
MyPreparedStatement的“奴隶”。真正干活的时候我们叫realPreparedStatement去做,我们自己的
MyPreparedStatement只在前后做一点自己的事情就好了,比如统计sql语句执行的时间,记录sql语句执行的内容,甚至在真正的sql
执行前进行修改来优化它。更深入点,我们甚至可以对不同的数据库的方言(dialect)进行相应的解释来转化成当前
realPreparedStatement对应的数据库的本地方言,当然你需要自己解析(parse)SQL语法。下面我们只谈简单的sql语句打印实
现。由于PreparedStatement执行sql时,比如execute()方法,并没有传入的sql语句,我们需要自己构造其真正要执行的sql
语句的原型,因此除了realPreparedStatement变量外,我们还需要几个辅助构造sql语句的成员变量。那么需要什么呢?我们可以想象,
一条简单的DML的sql语句的构成及其格式。主要讨论的就是PreparedStatement的’?’怎么可以替换成我们真正传入的数据。我们可以构
造两个列表或者数组,无论是什么,我们可以叫容器,一个存放带“‘’”的类型数据,一个存放不带“‘’”的类型的数据。比如:
CREATE TABLE T1(C1 INT PRIMARY KEY NOT NULL,C2 VARCHAR(20)) ;
我们传入给PreparedStatement的INSERT语句是:
INSERT INTO T1(C1,C2) VALUES(?,?);
如果真正数据时:1,’2009FLY’;的话,我们希望构成的是:
INSERT INTO T1(1,’2009FLY’);
当然,你也可以用其他的算法,比如一个存放容器value,另一个存放flag来标记是否该加”’’”,下面的实现就用的第二种算法。
那么到底什么类型该加”’’”,什么时候不该加”’’”;呢?聪明的你一定知道。但是要注意区分不同的数据库和同一种数据库的不同JDBC驱动,比
如SQLite的JDBC驱动,在SQLite里面就没有通常DBMS的数据类型。还有就是对于setObject()这样的方法的处理,这是一定要注意
的。好了,开始构造我们的MyPreparedStatement吧:
package com.2009fly;
import … …//请自行添加
public class MyPreparedStatement implements PreparedStatement{
private Connection myConnection;
private PreparedStatement realPreparedStatement;
private String sql;//欲处理的sql语句,带有’?’
… …//其它变量
public MyPreparedStatement (Connection conn,PreparedStatement ps,String sql){
this.myConnection =conn;//这个传入我们自己的Connection
this.realPreparedStatement=ps;//传入真正的realPreparedStatement
this.sql=sql;
}
… …
}
现在看看在MyConnection里面是怎么做的:
public PreparedStatement prepareStatement(String sql)
throws SQLException{
PreparedStatement ps = null;
ps=new MyPreparedStatement(this, realConnection.prepareStatement(sql),sql);
return ps;
}
Statement和PreparedStatement是类似的,但是后者的sql语句还要自己去构造,前面已经告诉了你的方法,可以在MyPreparedStatement里面再声明几个变量:
public final static int MAX_FIELDS = 32;//初始化数组大小
public static int GROW_MAX = 16;//超出MAX_FIELDS后自增大小
private Object values[];//set方法中的值
private boolean flag[]; //对应的values是否是含有引号的数据类型
在构造函数中添加:
values = new Object[MAX_FIELDS+1];
flag = new boolean[MAX_FIELDS+1];
这里values和flag是一一对应的。
我们这样子实现setTime()方法:
public void setTime(int p0, Time p1) throws SQLException {
setObjectAsString(p0, p1);//value[p0]=p1,flag[p0]=true;注意p0>MAX_FIELDS的处理
prepStmtPassthru.setTime(p0,p1);
}
在执行execute时候,根据sql,value和flag来构造真正的标准sql语句。这个就不写出来了,你会的!
目前你可以写自己的JDBC驱动工具来打印sql日志了,再加上个时间的函数,就可以检查每条sql执行所用的时间。再深一点,你加入sql解析,就可以转换不同DBMS的方言了,希望你能走的更远。
呵呵… …今天就到这里了,如果你还有不明白的地方,可以email给我:zzcwfp@gmail.com
====================================================================
版权所有,欢迎转载,请在转载前注明原文出处:正正博客 http://www.2009fly.com
尊重别人的劳动成果也就是尊重自己!
推荐:2009FLY文摘|正正博客
====================================================================
还从没有写过连载的文章,但是上次说的不是很完整,那天晚上把人困的不行,今天补过来。晚上就要回家了,一星期不能上网,这应该是春节前的最后一篇吧。
前面我们已经有了自己的JDBC的驱动MyDriver和与数据库的连接对象MyConnection。因为连接数据库是要和底层打交道的,必须主
动的去关闭与数据库的连接,因此千万认真的实现这几个资源的close方
法:Connection,Statenment,PreparedStatement,ResultSet等。好了,切入正题,我们今天讨论一下
PreparedStatement的写法,因为其是Statement的子对象,会了PreparedStatement的书写,那么
Statement也就不在话下了。
首先,和前面介绍的思想一下,要有一个真正干活的家伙:realPreparedStatement来作为我们自己的
MyPreparedStatement的“奴隶”。真正干活的时候我们叫realPreparedStatement去做,我们自己的
MyPreparedStatement只在前后做一点自己的事情就好了,比如统计sql语句执行的时间,记录sql语句执行的内容,甚至在真正的sql
执行前进行修改来优化它。更深入点,我们甚至可以对不同的数据库的方言(dialect)进行相应的解释来转化成当前
realPreparedStatement对应的数据库的本地方言,当然你需要自己解析(parse)SQL语法。下面我们只谈简单的sql语句打印实
现。由于PreparedStatement执行sql时,比如execute()方法,并没有传入的sql语句,我们需要自己构造其真正要执行的sql
语句的原型,因此除了realPreparedStatement变量外,我们还需要几个辅助构造sql语句的成员变量。那么需要什么呢?我们可以想象,
一条简单的DML的sql语句的构成及其格式。主要讨论的就是PreparedStatement的’?’怎么可以替换成我们真正传入的数据。我们可以构
造两个列表或者数组,无论是什么,我们可以叫容器,一个存放带“‘’”的类型数据,一个存放不带“‘’”的类型的数据。比如:
CREATE TABLE T1(C1 INT PRIMARY KEY NOT NULL,C2 VARCHAR(20)) ;
我们传入给PreparedStatement的INSERT语句是:
INSERT INTO T1(C1,C2) VALUES(?,?);
如果真正数据时:1,’2009FLY’;的话,我们希望构成的是:
INSERT INTO T1(1,’2009FLY’);
当然,你也可以用其他的算法,比如一个存放容器value,另一个存放flag来标记是否该加”’’”,下面的实现就用的第二种算法。
那么到底什么类型该加”’’”,什么时候不该加”’’”;呢?聪明的你一定知道。但是要注意区分不同的数据库和同一种数据库的不同JDBC驱动,比
如SQLite的JDBC驱动,在SQLite里面就没有通常DBMS的数据类型。还有就是对于setObject()这样的方法的处理,这是一定要注意
的。好了,开始构造我们的MyPreparedStatement吧:
package com.2009fly;
import … …//请自行添加
public class MyPreparedStatement implements PreparedStatement{
private Connection myConnection;
private PreparedStatement realPreparedStatement;
private String sql;//欲处理的sql语句,带有’?’
… …//其它变量
public MyPreparedStatement (Connection conn,PreparedStatement ps,String sql){
this.myConnection =conn;//这个传入我们自己的Connection
this.realPreparedStatement=ps;//传入真正的realPreparedStatement
this.sql=sql;
}
… …
}
现在看看在MyConnection里面是怎么做的:
public PreparedStatement prepareStatement(String sql)
throws SQLException{
PreparedStatement ps = null;
ps=new MyPreparedStatement(this, realConnection.prepareStatement(sql),sql);
return ps;
}
Statement和PreparedStatement是类似的,但是后者的sql语句还要自己去构造,前面已经告诉了你的方法,可以在MyPreparedStatement里面再声明几个变量:
public final static int MAX_FIELDS = 32;//初始化数组大小
public static int GROW_MAX = 16;//超出MAX_FIELDS后自增大小
private Object values[];//set方法中的值
private boolean flag[]; //对应的values是否是含有引号的数据类型
在构造函数中添加:
values = new Object[MAX_FIELDS+1];
flag = new boolean[MAX_FIELDS+1];
这里values和flag是一一对应的。
我们这样子实现setTime()方法:
public void setTime(int p0, Time p1) throws SQLException {
setObjectAsString(p0, p1);//value[p0]=p1,flag[p0]=true;注意p0>MAX_FIELDS的处理
prepStmtPassthru.setTime(p0,p1);
}
在执行execute时候,根据sql,value和flag来构造真正的标准sql语句。这个就不写出来了,你会的!
目前你可以写自己的JDBC驱动工具来打印sql日志了,再加上个时间的函数,就可以检查每条sql执行所用的时间。再深一点,你加入sql解析,就可以转换不同DBMS的方言了,希望你能走的更远。
呵呵… …今天就到这里了,如果你还有不明白的地方,可以email给我:zzcwfp@gmail.com
====================================================================
版权所有,欢迎转载,请在转载前注明原文出处:正正博客 http://www.2009fly.com
尊重别人的劳动成果也就是尊重自己!
推荐:2009FLY文摘|正正博客
====================================================================
相关文章推荐
- 自己动手写JDBC驱动来监视SQL语句(1)
- 自己动手写JDBC驱动来监视SQL语句(2)
- 自己动手写JDBC驱动来监视SQL语句(1)
- 自己动手写JDBC驱动来监视SQL语句
- 自己动手写数据库(一) 从SQL语句开始
- JDBC 初始化驱动 连接 执行sql语句 关闭连接
- 自己实现一个SQL解析引擎 功能:将用户输入的SQL语句序列转换为一个可执行的操作序列,并返回查询的结果集。 SQL的解析引擎包括查询编译与查询优化和查询的运行,主要包括3个步骤: 查询分析
- X5 自己系统用到的sql 语句
- SQLServer中监视sql执行的时间,比较sql语句的效率
- 自己整理的sql语句
- 自己初学数据库的笔记(oracle为主) (附带在网上看到的一个对SQL语句的小结见附件)
- 监视SQL语句在数据库中的运行情况
- JDBC系列:(3)使用PreparedStatement执行sql语句
- 自己总结的一些SQL语句的基本知识
- 自己动手写驱动禁用电脑主板喇叭!!
- 自己动手实现mybatis动态sql的方法
- Oracle.DataAccess 驱动使用因为SQL语句缓存报错问题解决办法
- DBA常用Sql语句--留着给自己看
- 让JAVA的JDBC支持命名参数的SQL语句
- 监视SQL语句在数据库中的运行