java连接mysql
方法
快递客服问题件处理详细方法山木方法pdf计算方法pdf华与华方法下载八字理论方法下载
.txt
Java连接数据库(以MySQL为例)2007-04-05 02:23 这篇文章主要以MySQL为例讲
下Java如何连接到数据库的。
当然,首先要安装有JDK(一般是JDK1.5.X)。然后安装MySQL,这些都比较简
单,具体过程就不说了。配置好这两个环境后,下载JDBC驱动
mysql-connector-java-5.0.5.zip(这个是最新版的)。然后将其解压缩到任一目录。我是
解压到D盘,然后将其目录下的mysql-connector-java-5.0.5-bin.jar加到classpath里,具
体如下:“我的电脑”-> “属性” -> “高级” -> “环境变量”
,在系统变量那里编辑classpath,将
D:\mysql-connector-java-5.0.5\mysql-connector-java-5.0.5-bin.jar加到最后,在加这
个字符串前要加“;”,以与前一个classpath区分开。然后确定。
环境配置好了,很简单。现在,先配置MySQL,设其用户名为“root”,密码为
“root”。在命令行或用一个SQL的前端软件创建Database。
没怎么用Jcreator Drivers的路进因该要设置,看看在classpath上加上driver路径
用eclipse吧
JDBC详解 收藏
在以java application server应用为主的平台是,JDBC的最高级应用是DataSource的实现,
其它的,JDO,webcache,hibernate等
不过是一种封装,所以看数据库应用的性能,主要看据库连结的利用率,所以,DataSource可以
说是J2EE最最重要的应
用.
对于主流的数据库,如mysql,mssqlserver,oracle,从其通用的性能来看,我建议在JAVA平台
上应用oracle和mysql,MS的数
据库在JAVA平台上的性能只能达到上述两种数据库的60-70%,在相同硬件的基础是,做同样的
操作,测试了这三种数
据库对并发的支持,MYSQL最高为430,ORACLE为400,SQLSERVER只有250.
如果你不得不用SQLSERVER作为JAVA平台的数据库,那么一个合适的JDBC是最最重要的,MS自
己提供的JDBC到目前为
止并不能真正支持DataSource,不过bea的weblogic8中已经内置了type4的ms sqlserver的
JDBC,这是一个真正支
持DataSource的JDBC,如果你不得不用sqlserver,你可以把这个JDBC从BEA的WLS中驳离出来.
另外一点,如果你的J2EE应用主要集中在jsp/servlet,而后台数据库采用oracle的话,那么你
有福了.你不要采用其它
的WEB容器,在oracle8.17以后的版本中都内置了servlet引擎.
如果你基于这个引擎,你会获得其它应用组合所无法比拟的性能,因为ORACLE的WEB容器是工
作在数据库的地址空
间,想一想,这意味着什么?
这就意味着,容器对数据库的访问是"本地文件存取方式",虽然oracle也提供了
标准
excel标准偏差excel标准偏差函数exl标准差函数国标检验抽样标准表免费下载红头文件格式标准下载
的JDBC接
第 1 页
java连接mysql方法.txt
口让调用者调用,但事实
上这时的Connection对象只相当于一个文件句柄,而其它的JDBC连结都是封装了Socket,通过
Socket和数据库进行通讯,
如果你不理解这里的区别,那我打一个比方:就好象两个人面对面谈话和通过国际长途谈话的
区别,这其间的性能怎
一个高字了得.
mysql从来就是被设计为"网络数据库",针对数据安全性不是太重要的应用.它的最大优点是
通用,性能高,速度快,安
全性较低,对于不是机密要件的应用,用MYSQL肯定没错.
MS SQLSERVER,除了在JAVA平台上性能表现不好外,没有什么可说的,如果换在WIN平台上,它
是顶级首选项,没有任何
数据库在WIN平台上可以和它做任何方面的比较.
ORACLE,JAVA平台上的老大,除去成本因素,在JAVA平台上没有理由不选择它.
本来不想写这部份入门级的内容,但既然栏目定为JDBC专栏,还是简单写一些吧.
来,我们认识一下!
JDBC,JAVA平台的DATABASE的连通性.白话一句,什么意思啊?
就是JAVA平台上和数据库进行连结的"工具".
还是先一起来回顾一下接口吧:从下向上,接口是对"案例"的抽象,由一个案例抽象出一些规
则.
反过来,从上向下,被抽象出来的接口是对案例的一种承诺和约束.
也就是说,只要你实现我规定的接口,你的类就已经具有了接口对外承诺的方法,只要"客户"
会
操作接口,不需要重新学习就会操作实现了该接口的新类!
好了,用行话来说:
1.通过接口可以实现不相关的类的相同行为.
2.通过接口可以指明多个类需要实现的方法.
3.通过接口可以了解对象的交互方法而不需要了解对象所对应的类蓝本.
这几句话很明白吧?好象有一本什么模式的书把这段话用了30多页写出来,结果别人看了还不
如
我这几句话明白,不过我明白了为什么有些人要写书了.
搞懂了以上这东西,JDBC就好明白了.
为了通用,JAVA中要求有一种机制,在操作不同厂商数据库时有相同的方法去操作,而不是每
接
触一种数据库就要学习新的方法.完成这种机制的"东西"就叫"JDBC"了.
简单地分,JDBC有两部分组成,JDBC API和JDBC Driver Interface.
JDBC API就是提供给"客户"(就是象你我这种菜鸟级程序员来用的,如果是高手都自己写JDBC
了,
哈哈)的一组独立于数据库的API,对任何数据库的操作,都可以用这组API来进行.那么要把这
些通用的API
翻译成特定数据库能懂的"指令",就要由JDBC Driver Interface来实现了,所以这部份是面
向JDBC驱动程
序开发商的编程接口,它会把我们通过JDBC API发给数据库的通用指令翻译给他们自己的数
据库.
第 2 页
java连接mysql方法.txt
还是通过实际操作来看看JDBC如何工作的吧.
因为JDBC API是通用接口,那么程序是如何知道我要连结的是哪种数据库呢?所以在和数据库
连
结时先要加载(或注册可用的Driver),其实就是JDBC签名.加载驱动程序和好多方法,最常用
的就是先把驱
动程序类溶解到内存中,作为"当前"驱动程序.注意"当前"是说内存中可以有多个驱动程序,
但只有现在加
载的这个作为首选连结的驱动程序.
Class.forName("org.gjt.mm.mysql.Driver");
Class.forName方法是先在内存中溶解签名为"org.gjt.mm.mysql.Driver"的Driver类,
Driver类
就会把相应的实现类对应到JDBC API的接口中.比如把org.gjt.mm.mysql.Connection的实例
对象赋给
java.sql.Connection接口句柄,以便"客户"能通过操作java.sql.Connection句柄来调用实
际的
org.gjt.mm.mysql.Connection中的方法.之于它们是如果映射的,这是厂商编程的,"客户"只
要调用
Class.forName("org.gjt.mm.mysql.Driver");方法就可以顺利地操作JDBC API了.
一个普通数据库的连结过程为:
1.加载驱动程序.
2.通过DriverManager到得一个与数据库连结的句柄.
3.通过连结句柄绑定要执行的语句.
4.接收执行结果.
5.可选的对结果的处理.
6.必要的关闭和数据库的连结.
因为是基础篇,所以还是对每一步骤简单说明一下吧:
前面说是,注册驱动程序有多方法,Class.forName();是一种显式地加载.当一个驱
动程序类被Classloader装载后,在溶解的过程中,DriverManager会注册这个驱动类的实例.
这个调用是自动发生的,也就是说DriverManager.registerDriver()方法被自动调用了,当然
我们也可以直接调用DriverManager.registerDriver()来注册驱动程序,但是,以我的经验.
MS的浏览中APPLET在调用这个方法时不能成功,也就是说MS在浏览器中内置的JVM对该方法的
实现是无效的.
另外我们还可以利用系统属性jdbc.drivers来加载多个驱动程序:
System.setProperty("jdbc.drivers","driver1:driver2:.....:drivern");多个驱动程序
之
间用":"隔开,这样在连结时JDBC会按顺序搜索,直到找到第一个能成功连结指定的URL的驱动
程序.
在基础篇里我们先不介绍DataSource这些高级特性.
在成功注册驱动程序后,我们就可以用DriverManager的静态方法getConnection来得
到和数据库连结的引用:
Connection conn = DriverManager.getConnection(url);
如果连结是成功的,则返回Connection对象conn,如果为null或抛出异常,则说明没有
和数据库建立连结.
对于getConnection()方法有三个重载的方法,一种是最简单的只给出数据源即:
getConnection(url),另一种是同时给出一些数据源信息即
getConnection(url,Properties),
另外一种就是给出数据源,用户名和密码:getConnection(url,user,passwod),对于数据源信
息.
如果我们想在连结时给出更多的信息可以把这些信息压入到一个Properties,当然可以直接
第 3 页
java连接mysql方法.txt
压
入用户名密码,别外还可以压入指定字符集,编码方式或默认操作等一些其它信息.
在得到一个连结后,也就是有了和数据库找交道的通道.我们就可以做我们想要的操
作了.
还是先来介绍一些一般性的操作:
如果我们要对数据库中的表进行操作,要先缘故绑定一个语句:
Statement stmt = conn.createStatement();
然后利用这个语句来执行操作.根本操作目的,可以有两种结果返回,如果执行的查询
操作,返回为结果集ResultSet,如果执行更新操作,则返回操作的记录数int.
注意,SQL操作严格区分只有两个,一种就是读操作(查询操作),另一种就是写操作(更
新操作),所以,create,insert,update,drop,delete等对数据有改写行为的操作都是更新操
作.
ResultSet rs = stmt.executeQuery("select * from table where xxxxx");
int x = stmt.executeUpdate("delete from table where ......");
如果你硬要用executeQuery执行一个更新操作是可以的,但不要把它赋给一个句柄,
当然稍微有些经验的程序员是不会这么做的.
至于对结果集的处理,我们放在下一节讨论,因为它是可操作的可选项,只有查询操作
才返回结果集,对于一次操作过程的完成,一个非常必要的步骤是关闭数据库连结,在你没有
了
解更多的JDBC知识这前,你先把这一步骤作为JDBC操作中最最重要的一步,在以后的介绍中我
会
不断地提醒你去关闭数据库连结!!!!!!!!!!!
按上面介绍的步骤,一个完成的例子是这样的:(注意,为了按上面的步骤介绍,这个例
子不是最好的)
try{
Class.forName("org.gjt.mm.mysql.Driver");
}catch(Exception e){
System.out.println("没有成功加载驱动程序:"+e.toString());
return;
}//对于象我这样的经验,可以直接从e.toString()的简单的几个字判断出异常原因,
//如果你是一个新手应该选捕获它的子类,如何知道要捕获哪几个异常呢?一个简单
//的方法就是先不加try{},直接Class.forName("org.gjt.mm.mysql.Driver");,编
//译器就会告诉你要你捕获哪几个异常了,当然这是偷机取巧的方法,最好还是自己
//去看JDK文档,它会告诉你每个方法有哪些异常要你捕获.
Connection conn = null;
try{
conn = DriverManager.getConnection(
"jdbc:mysql://host:3306/mysql",
"user",
"passwd");
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("select * from table");
//rs 处理
[rs.close();]
[stmt.close();]
}
catch(Exception e){
System.out.println("数据库操作出现异常:"+e.toString());
}
finally{
try{conn.close();}catch(Exception){}
}//不管你以前是学习到的关于数据库流程是如何操作的,如果你相信我,从现在开始,
//请你一定要把数据库关闭的代码写到finally块中,切切!
第 4 页
java连接mysql方法.txt
关于Statement对象:
前面说过,Statement对象是用来绑定要执行的操作的,在它上面有三种执行方法:
即用来执行查询操作的executeQuery(),用来执行更新操作的executeUpdate()和用来执行
动态的未知的操作的execute().
JDBC在编译时并不对要执行的SQL语句检测,只是把它看着一个String,只有在驱动
程序执行SQL语句时才知道正确与否.
一个Statement对象同时只能有一个结果集在活动.这是宽容性的,就是说即使没有
调用ResultSet的close()方法,只要打开第二个结果集就隐含着对上一个结果集的关闭.所以
如果你想同时对多个结果集操作,就要创建多个Statement对象,如果不需要同时操作,那么可
以在一个Statement对象上须序操作多个结果集.
这里我不得不特别说明一下,很多人会用一个Statement进行嵌套查询,然后就来问
我说为什么不能循环?道理上面已经说清楚了.我们来详细
分析
定性数据统计分析pdf销售业绩分析模板建筑结构震害分析销售进度分析表京东商城竞争战略分析
一下嵌套查询:
Connection conn = null;
Statement stmt = null;
conn = .......;
stmt = conm.createStatement(xxxxxx);
ResultSet rs = stmt.executeQuery(sql1);
while(rs.next()){
str = rs.getString(xxxxx);
ResultSet rs1 = stmt.executeQuery("select * from 表 where 字段=str");
}
当stmt.executeQuery("select * from 表 where 字段=str");赋给rs1时,这时隐含的操作
是已经关闭了rs,你还能循环下去吗?
所以如果要同时操作多个结果集一定要让它他绑定到不同的Statement对象上.好在一个
connection
对象可以创建任意多个Statement对象,而不需要你重新获取连结.
关于获取和设置Statement的选项:只要看看它的getXXX方法和setXXX方法就明白了,这儿
作为基础知识只提一下以下几个:
setQueryTimeout,设置一个SQL执行的超时限制.
setMaxRows,设置结果集能容纳的行数.
setEscapeProcessing,如果参数为true,则驱动程序在把SQL语句发给数据库前进行转义替
换,否则让数据库自己处理,当然这些默认值都可以通过get方法查询.
Statement的两个子类:
PreparedStatement:对于同一条语句的多次执行,Statement每次都要把SQL语句发送给数据
库,这样做效率明显不高,而如果数据库支持预编译,PreparedStatement可以先把要执行的语
句一次发
给它,然后每次执行而不必发送相同的语句,效率当然提高,当然如果数据库不支持预编译,
PreparedStatement会象Statement一样工作,只是效率不高而不需要用户工手干预.
另外PreparedStatement还支持接收参数.在预编译后只要传输不同的参数就可以执行,大大
提高了性能.
PreparedStatement ps = conn.prepareStatement("select * from 表 where 字段=?");
ps.setString(1,参数);
ResultSet rs = ps.executeQuery();
CallableStatement:是PreparedStatement的子类,它只是用来执行存储过程的.
CallableStatement sc = conn.prepareCall("{call query()}");
ResultSet rs = cs.executeQuery();
> 删除 . 2010-01-01 22:45:18 茫茫 (肩膀有双翅膀) 大恩不言谢啊
研究中......
> 删除 . 2010-01-02 11:36:23 快乐就好 JDBC详解 收藏(classpath里加上diver的路径)
第 5 页
java连接mysql方法.txt
在以java application server应用为主的平台是,JDBC的最高级应用是DataSource的实现,
其它的,JDO,webcache,hibernate等
不过是一种封装,所以看数据库应用的性能,主要看据库连结的利用率,所以,DataSource可以
说是J2EE最最重要的应
用.
对于主流的数据库,如mysql,mssqlserver,oracle,从其通用的性能来看,我建议在JAVA平台
上应用oracle和mysql,MS的数
据库在JAVA平台上的性能只能达到上述两种数据库的60-70%,在相同硬件的基础是,做同样的
操作,测试了这三种数
据库对并发的支持,MYSQL最高为430,ORACLE为400,SQLSERVER只有250.
如果你不得不用SQLSERVER作为JAVA平台的数据库,那么一个合适的JDBC是最最重要的,MS自
己提供的JDBC到目前为
止并不能真正支持DataSource,不过bea的weblogic8中已经内置了type4的ms sqlserver的
JDBC,这是一个真正支
持DataSource的JDBC,如果你不得不用sqlserver,你可以把这个JDBC从BEA的WLS中驳离出来.
另外一点,如果你的J2EE应用主要集中在jsp/servlet,而后台数据库采用oracle的话,那么你
有福了.你不要采用其它
的WEB容器,在oracle8.17以后的版本中都内置了servlet引擎.
如果你基于这个引擎,你会获得其它应用组合所无法比拟的性能,因为ORACLE的WEB容器是工
作在数据库的地址空
间,想一想,这意味着什么?
这就意味着,容器对数据库的访问是"本地文件存取方式",虽然oracle也提供了标准的JDBC接
口让调用者调用,但事实
上这时的Connection对象只相当于一个文件句柄,而其它的JDBC连结都是封装了Socket,通过
Socket和数据库进行通讯,
如果你不理解这里的区别,那我打一个比方:就好象两个人面对面谈话和通过国际长途谈话的
区别,这其间的性能怎
一个高字了得.
mysql从来就是被设计为"网络数据库",针对数据安全性不是太重要的应用.它的最大优点是
通用,性能高,速度快,安
全性较低,对于不是机密要件的应用,用MYSQL肯定没错.
MS SQLSERVER,除了在JAVA平台上性能表现不好外,没有什么可说的,如果换在WIN平台上,它
是顶级首选项,没有任何
第 6 页
java连接mysql方法.txt
数据库在WIN平台上可以和它做任何方面的比较.
ORACLE,JAVA平台上的老大,除去成本因素,在JAVA平台上没有理由不选择它.
本来不想写这部份入门级的内容,但既然栏目定为JDBC专栏,还是简单写一些吧.
来,我们认识一下!
JDBC,JAVA平台的DATABASE的连通性.白话一句,什么意思啊?
就是JAVA平台上和数据库进行连结的"工具".
还是先一起来回顾一下接口吧:从下向上,接口是对"案例"的抽象,由一个案例抽象出一些规
则.
反过来,从上向下,被抽象出来的接口是对案例的一种承诺和约束.
也就是说,只要你实现我规定的接口,你的类就已经具有了接口对外承诺的方法,只要"客户"
会
操作接口,不需要重新学习就会操作实现了该接口的新类!
好了,用行话来说:
1.通过接口可以实现不相关的类的相同行为.
2.通过接口可以指明多个类需要实现的方法.
3.通过接口可以了解对象的交互方法而不需要了解对象所对应的类蓝本.
这几句话很明白吧?好象有一本什么模式的书把这段话用了30多页写出来,结果别人看了还不
如
我这几句话明白,不过我明白了为什么有些人要写书了.
搞懂了以上这东西,JDBC就好明白了.
为了通用,JAVA中要求有一种机制,在操作不同厂商数据库时有相同的方法去操作,而不是每
接
触一种数据库就要学习新的方法.完成这种机制的"东西"就叫"JDBC"了.
简单地分,JDBC有两部分组成,JDBC API和JDBC Driver Interface.
JDBC API就是提供给"客户"(就是象你我这种菜鸟级程序员来用的,如果是高手都自己写JDBC
了,
哈哈)的一组独立于数据库的API,对任何数据库的操作,都可以用这组API来进行.那么要把这
些通用的API
翻译成特定数据库能懂的"指令",就要由JDBC Driver Interface来实现了,所以这部份是面
向JDBC驱动程
序开发商的编程接口,它会把我们通过JDBC API发给数据库的通用指令翻译给他们自己的数
据库.
还是通过实际操作来看看JDBC如何工作的吧.
因为JDBC API是通用接口,那么程序是如何知道我要连结的是哪种数据库呢?所以在和数据库
连
结时先要加载(或注册可用的Driver),其实就是JDBC签名.加载驱动程序和好多方法,最常用
的就是先把驱
动程序类溶解到内存中,作为"当前"驱动程序.注意"当前"是说内存中可以有多个驱动程序,
但只有现在加
载的这个作为首选连结的驱动程序.
Class.forName("org.gjt.mm.mysql.Driver");
Class.forName方法是先在内存中溶解签名为"org.gjt.mm.mysql.Driver"的Driver类,
Driver类
就会把相应的实现类对应到JDBC API的接口中.比如把org.gjt.mm.mysql.Connection的实例
对象赋给
java.sql.Connection接口句柄,以便"客户"能通过操作java.sql.Connection句柄来调用实
际的
org.gjt.mm.mysql.Connection中的方法.之于它们是如果映射的,这是厂商编程的,"客户"只
要调用
第 7 页
java连接mysql方法.txt
Class.forName("org.gjt.mm.mysql.Driver");方法就可以顺利地操作JDBC API了.
一个普通数据库的连结过程为:
1.加载驱动程序.
2.通过DriverManager到得一个与数据库连结的句柄.
3.通过连结句柄绑定要执行的语句.
4.接收执行结果.
5.可选的对结果的处理.
6.必要的关闭和数据库的连结.
因为是基础篇,所以还是对每一步骤简单说明一下吧:
前面说是,注册驱动程序有多方法,Class.forName();是一种显式地加载.当一个驱
动程序类被Classloader装载后,在溶解的过程中,DriverManager会注册这个驱动类的实例.
这个调用是自动发生的,也就是说DriverManager.registerDriver()方法被自动调用了,当然
我们也可以直接调用DriverManager.registerDriver()来注册驱动程序,但是,以我的经验.
MS的浏览中APPLET在调用这个方法时不能成功,也就是说MS在浏览器中内置的JVM对该方法的
实现是无效的.
另外我们还可以利用系统属性jdbc.drivers来加载多个驱动程序:
System.setProperty("jdbc.drivers","driver1:driver2:.....:drivern");多个驱动程序
之
间用":"隔开,这样在连结时JDBC会按顺序搜索,直到找到第一个能成功连结指定的URL的驱动
程序.
在基础篇里我们先不介绍DataSource这些高级特性.
在成功注册驱动程序后,我们就可以用DriverManager的静态方法getConnection来得
到和数据库连结的引用:
Connection conn = DriverManager.getConnection(url);
如果连结是成功的,则返回Connection对象conn,如果为null或抛出异常,则说明没有
和数据库建立连结.
对于getConnection()方法有三个重载的方法,一种是最简单的只给出数据源即:
getConnection(url),另一种是同时给出一些数据源信息即
getConnection(url,Properties),
另外一种就是给出数据源,用户名和密码:getConnection(url,user,passwod),对于数据源信
息.
如果我们想在连结时给出更多的信息可以把这些信息压入到一个Properties,当然可以直接
压
入用户名密码,别外还可以压入指定字符集,编码方式或默认操作等一些其它信息.
在得到一个连结后,也就是有了和数据库找交道的通道.我们就可以做我们想要的操
作了.
还是先来介绍一些一般性的操作:
如果我们要对数据库中的表进行操作,要先缘故绑定一个语句:
Statement stmt = conn.createStatement();
然后利用这个语句来执行操作.根本操作目的,可以有两种结果返回,如果执行的查询
操作,返回为结果集ResultSet,如果执行更新操作,则返回操作的记录数int.
注意,SQL操作严格区分只有两个,一种就是读操作(查询操作),另一种就是写操作(更
新操作),所以,create,insert,update,drop,delete等对数据有改写行为的操作都是更新操
作.
ResultSet rs = stmt.executeQuery("select * from table where xxxxx");
int x = stmt.executeUpdate("delete from table where ......");
如果你硬要用executeQuery执行一个更新操作是可以的,但不要把它赋给一个句柄,
当然稍微有些经验的程序员是不会这么做的.
第 8 页
java连接mysql方法.txt
至于对结果集的处理,我们放在下一节讨论,因为它是可操作的可选项,只有查询操作
才返回结果集,对于一次操作过程的完成,一个非常必要的步骤是关闭数据库连结,在你没有
了
解更多的JDBC知识这前,你先把这一步骤作为JDBC操作中最最重要的一步,在以后的介绍中我
会
不断地提醒你去关闭数据库连结!!!!!!!!!!!
按上面介绍的步骤,一个完成的例子是这样的:(注意,为了按上面的步骤介绍,这个例
子不是最好的)
try{
Class.forName("org.gjt.mm.mysql.Driver");
}catch(Exception e){
System.out.println("没有成功加载驱动程序:"+e.toString());
return;
}//对于象我这样的经验,可以直接从e.toString()的简单的几个字判断出异常原因,
//如果你是一个新手应该选捕获它的子类,如何知道要捕获哪几个异常呢?一个简单
//的方法就是先不加try{},直接Class.forName("org.gjt.mm.mysql.Driver");,编
//译器就会告诉你要你捕获哪几个异常了,当然这是偷机取巧的方法,最好还是自己
//去看JDK文档,它会告诉你每个方法有哪些异常要你捕获.
Connection conn = null;
try{
conn = DriverManager.getConnection(
"jdbc:mysql://host:3306/mysql",
"user",
"passwd");
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("select * from table");
//rs 处理
[rs.close();]
[stmt.close();]
}
catch(Exception e){
System.out.println("数据库操作出现异常:"+e.toString());
}
finally{
try{conn.close();}catch(Exception){}
}//不管你以前是学习到的关于数据库流程是如何操作的,如果你相信我,从现在开始,
//请你一定要把数据库关闭的代码写到finally块中,切切!
关于Statement对象:
前面说过,Statement对象是用来绑定要执行的操作的,在它上面有三种执行方法:
即用来执行查询操作的executeQuery(),用来执行更新操作的executeUpdate()和用来执行
动态的未知的操作的execute().
JDBC在编译时并不对要执行的SQL语句检测,只是把它看着一个String,只有在驱动
程序执行SQL语句时才知道正确与否.
一个Statement对象同时只能有一个结果集在活动.这是宽容性的,就是说即使没有
调用ResultSet的close()方法,只要打开第二个结果集就隐含着对上一个结果集的关闭.所以
如果你想同时对多个结果集操作,就要创建多个Statement对象,如果不需要同时操作,那么可
以在一个Statement对象上须序操作多个结果集.
这里我不得不特别说明一下,很多人会用一个Statement进行嵌套查询,然后就来问
我说为什么不能循环?道理上面已经说清楚了.我们来详细分析一下嵌套查询:
Connection conn = null;
Statement stmt = null;
conn = .......;
第 9 页
java连接mysql方法.txt
stmt = conm.createStatement(xxxxxx);
ResultSet rs = stmt.executeQuery(sql1);
while(rs.next()){
str = rs.getString(xxxxx);
ResultSet rs1 = stmt.executeQuery("select * from 表 where 字段=str");
}
当stmt.executeQuery("select * from 表 where 字段=str");赋给rs1时,这时隐含的操作
是已经关闭了rs,你还能循环下去吗?
所以如果要同时操作多个结果集一定要让它他绑定到不同的Statement对象上.好在一个
connection
对象可以创建任意多个Statement对象,而不需要你重新获取连结.
关于获取和设置Statement的选项:只要看看它的getXXX方法和setXXX方法就明白了,这儿
作为基础知识只提一下以下几个:
setQueryTimeout,设置一个SQL执行的超时限制.
setMaxRows,设置结果集能容纳的行数.
setEscapeProcessing,如果参数为true,则驱动程序在把SQL语句发给数据库前进行转义替
换,否则让数据库自己处理,当然这些默认值都可以通过get方法查询.
Statement的两个子类:
PreparedStatement:对于同一条语句的多次执行,Statement每次都要把SQL语句发送给数据
库,这样做效率明显不高,而如果数据库支持预编译,PreparedStatement可以先把要执行的语
句一次发
给它,然后每次执行而不必发送相同的语句,效率当然提高,当然如果数据库不支持预编译,
PreparedStatement会象Statement一样工作,只是效率不高而不需要用户工手干预.
另外PreparedStatement还支持接收参数.在预编译后只要传输不同的参数就可以执行,大大
提高了性能.
PreparedStatement ps = conn.prepareStatement("select * from 表 where 字段=?");
ps.setString(1,参数);
ResultSet rs = ps.executeQuery();
CallableStatement:是PreparedStatement的子类,它只是用来执行存储过程的.
CallableStatement sc = conn.prepareCall("{call query()}");
ResultSet rs = cs.executeQuery();
关于更高级的知识我们在JDBC高级应用中介绍.
作为基础知识的最后部分,我们来说一说结果集的处理,当然是说对一般结果集的处理.
至于存储过程返回的多结果集,我们仍然放在高级应用中介绍.
SQL语句如何执行的是查询操作,那就要返回一个ResultSet对象,要想把查询结果最后
明白地显示给用户,必须对ResultSet进行处理.ResultSet返回的是一个表中符合条件的记
录,对
ResultSet的处理要逐行处理,而对于每一行的列的处理,则可以按任意顺序(注意,这只是
JDBC规
范的要求,有些JDBC实现时对于列的处理仍然要求用户按顺序处理,但这是极少数的).事实
上,虽
然你可以在处理列的时候可以按任意顺序,但如果你按从左到右的顺序则可以得到较高的性
能.
这儿从底层来讲解一下ResultSet对象,在任何介绍JDBC的书上你是不会获得这样的知
识的,因为那是数据库厂商的事.ResultSet对象实际维护的是一个二维指针,第一维是指向当
前
行,最初它指向的是结果集的第一行之前,所以如果要访问第一行,就要先next(),以后每一行
都
要先next()才能访问,然后第二维的指针指向列,只要当你去rs.getXXX(列)时,才通过
Connection再去数据库把真实的数据取出来,否则没有什么机器能真的把要取的数据都放在
第 10 页
java连接mysql方法.txt
内
存中.
所以,千万要记住,如果Connection已经关闭,那是不可能再从ResultSet中取到数据的.
有很多人问我,我可不可以取到一个ResultSet把它写到Session中然后关闭Connection,这样
就
不要每次都连结了.我只能告诉你,你的想法非常好,但,是错误的!当然在javax.sql包中JDBC
高
级应用中有CacheRow和WebCacheRow可以把结果集缓存下来,但那和我们自己开一个数据结构
把
ResultSet的行集中所有值一次取出来保存起来没有什么两样.
访问行中的列,可以按字段名或索引来访问.下面是一个简单的检索结果的程序:
ResultSet rs = stmt.executeQuery("select a1,a2,a3 from table");
while(rs.next()){
int i = rs.getInt(1);
String a = rs.getString("a2");
..............
}
对于用来显示的结果集,用while来进行next()是最普通的,如果next()返回false,则
说明已经没有可用的行了.但有时我们可能连一行都没有,而如果有记录又不知道是多少行,
这时
如果要对有记录和没有记录进行不同的处理,应该用以下流程进行判断:
if(rs.next()){
//因为已经先next()了,所经对记录应该用do{}while();来处理
do{
int i = rs.getInt(1);
String a = rs.getString("a2");
}while(rs.next());
}
esle{
System.out.println("没有取得符合条件的记录!");
}
类型转换:
ResultSet的getXXX方法将努力把结果集中的SQL数据类型转换为JAVA的数据类型,事实
大多数类型是可以转换的,但仍然有不少糊弄是不能转换的,如你不能将一个SQL的float转换
成
JAVA的DATE,你无法将 VARCHAR "我们"转换成JAVA的Int.
较大的值:
对于大于Statement中getMaxFieldSize返回值的值,用普通的getBytes()或getString()
是不能读取的,好在JAVA提供了读取输入流的方法,对于大对象,我们可以通过
rs.getXXXStream()
来得到一个InputStream,XXX的类型包括Ascii,Binay,Unicode.根据你存储的字段类型来使
用不
同的流类型,一般来说,二进制文件用getBinayStream(),文本文件用getAsciiStyream(),对
于
Unicode字符的文本文件用getUnicodeStream(),相对应的数据库字段类型应该为:Blob,Clob
和
Nlob.
获取结果集的信息:
大多数情况下编程人员对数据库结构是了解的,可以知道结果集中各列的情况,但有时并
不知道结果集中有哪些列,是什么类型.这时可以通过getMetaData()来获取结果集的情况:
第 11 页
java连接mysql方法.txt
ResulSetMetaData rsmd = rs.getMetaData();
rsmd.getColumnCount()返回列的个数.
getColumnLabel(int)返回该int所对应的列的显示标题
getColumnName(int)返回该int所对应的列的在数据库中的名称.
getColumnType(int)返回该int所对应的列的在数据库中的数据类型.
getColumnTypeName(int)返回该int所对应的列的数据类型在数据源中的名称.
isReadOnly(int)返回该int所对应的列是否只读.
isNullable(int)返回该int所对应的列是否可以为空
在了解JDBC基础知识以后,我们先来写一个数据库操作的类(Bean)以后我们会
在这个类的基础上,随着介绍的深入不断提供优化的
方案
气瓶 现场处置方案 .pdf气瓶 现场处置方案 .doc见习基地管理方案.doc关于群访事件的化解方案建筑工地扬尘治理专项方案下载
.
要把一个数据库操作独立到一个类(Bean)中,至少要考虑以下几个方面:
1.对于不同层次的应用,应该有不同的得到连结的方法,如果得到连结的方法要随
着应用层次的不同而改变,我们就应该把他独立成一个专门的类中,而把在任何应用层次
中都通用的处理方法封装到一个(类)Bean中.
2.既然考虑到既作为javaBean使用又可以用为一个普通类调用,要考虑到javaBean
的
规范
编程规范下载gsp规范下载钢格栅规范下载警徽规范下载建设厅规范下载
和普通类的灵活性.
3.对于特定的数据库操作不应封装到共性的(类)Bean中,而应该成为它的扩展类.
以上几点是充分考虑JAVA的面象对象的思想,经过深入的抽象形成的层次,下面我
们就按这个思想来设计:
一:定义一个用于连结的Bean,以后如果要在不同的应用中,如可以在J2EE中从
DataSource中得到连结,或从普通的连结池中得到连结,以及直接从DriverManager中得到
连结,只需修改本类中的得到连结的实现方法.
package com.imnamg.axman.beans;
import java.sql.*;
import ..................
public class ConnectionFactory{
protected Connection conn;
ConnectionFactory() throws SQLException
{ //构造方法中生成连结
//无论是从DataSource还是直接从DriverManager中取得连结.
//先初始化环境,然后取得连结,本例作为初级应用,从
//DriverManager中取得连结,因为是封装类,所以要把异常抛
//给调用它的程序处理而不要用try{}catch(){}块自选处理了.
//因为要给业务方法的类继承,而又不能给调用都访问,所以
//conn声明为protected
conn = DriverManager.getConnection(url,user,passwd);
}
/**
在多线程编程中,很多时候有可能在多个线程体中得到同一连
结的引用,但如果在一个线程中关闭了连结,则另一个得到相同
引用的线程就无法操作了,所以我们应该加一个重新建立连结
的辅助方法,有人问为什么既然有这个辅助方法不直接调用这个
辅助而要在构造方法中生成连结?因为这样可以增加效率,如果
在构造时不能生成连结则就不能生成这个对象了,没有必要在
对象生成后再测试能不能生成连结.
*/
public void makeConnection(){
//此处的代码同构造方法,无论以后如果实现连结,都将构造方
//法的代码复制到此处.
conn = DriverManager.getConnection(url,user,passwd);
}
}
第 12 页
java连接mysql方法.txt
这个类就封装到这里,当然你可以在这儿增加业务方法,但如果要修改连结的实现,
整个类都要重新编译,因为业务方法和应用层次无关,代码一经生成不易变动,所以独立封装.
以下我们实现业务方法:
package com.imnamg.axman.beans;
import java.sql.*;
import ..................
public class DBOperater extends ConnectionFactory{
//private Statement stmt;
//private ResultSet rs;
//为什么要注释成员变量stmt和rs,基础部分已经说过,如果声明为成员变量,
//在关闭conn时可以显示地先关闭rs和stmt,别的没有任何好处,而显示关
//闭只是说明你编程风格好,但综合考虑,我们要生成多个stmt或不是类型的
//stmt就不能声明为成员方法,否则引用同一对象,所以我们要业务方法中生
//成stmt对象.不仅可以同时处理多个结果集,还可以提高性能和灵活性.
public ResultSet executeQuery(String sql) throws SQLException{
if(conn==null || conn.isClosed())
makeConnection();
Statement stmt = con.createStatement(
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
//对于一般的查询操作,我们只要生成一个可流动的结果集就行了.
//而对于在查询时要更新记录,我们用另一个业务方法来处理,这样,
//这样可以在普通查询时节省回滚空间.
ResultSet rs = stmt.executeQuery(sql);
return rs;
}
public ResultSet executeUpdatabledQuery(String sql) throws SQLException{
if (con == null || con.isClosed())
makeConnection();
Statement stmt = con.createStatement(
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_UPDATABLED);
//可更新的结果结要更大的回滚空间,普通查询时不要调用这个方法
ResultSet rs = stmt.executeQuery(sql);
return rs;
}
/**
基于同上的原因,在执行更新操作是我们根本不要任何回滚空间,所以建立
一个基本类型的stmt,实现如下
*/
public int executeUpdate(String sql) throws SQLException{
if (con == null || con.isClosed())
makeConnection();
Statement stmt = con.createStatement();
//这个stmt在执行更新操作时更加节省内存,永远记住,能节省的时候要节省
//每一个字节的内存,虽然硬件设备可能会有很大的物理内存,但内存是给用
//户用的而不是给程序员用的(!!!!!!!!!!!!!!!!!!)
int s = stmt.executeUpdate(sql);
return s;
第 13 页
java连接mysql方法.txt
}
//以上实现了常用功能,还有两个通用的功能也是"共性"的,我们一起在这个封装类
//中实现:
public PreparedStatement getPreparedStmt(String sql) throws SQLException{
if (con == null || con.isClosed())
makeConnection();
PreparedStatement ps = con.prepareStatement(sql);
return p