JavaJDBC学习教程由浅入深.docx
- 文档编号:6946956
- 上传时间:2023-01-13
- 格式:DOCX
- 页数:126
- 大小:338.39KB
JavaJDBC学习教程由浅入深.docx
《JavaJDBC学习教程由浅入深.docx》由会员分享,可在线阅读,更多相关《JavaJDBC学习教程由浅入深.docx(126页珍藏版)》请在冰豆网上搜索。
JavaJDBC学习教程由浅入深
第一节整理目的
当今orm等全自动针对对象持久化的框架越来越多并且也越来越成熟(ibatis,hibernate,ejb的jpa),但是无奈新东家需要使用jdbc(原始手工作坊)的模式和数据库打交道,用了几年的ibatis,再次使用jdbc发现有些细节和底层的东西自己并不是十分清楚,所以就啰理啰嗦的整理出一份学习笔记,第一作为自己对jdbc重新的复习,第二如果有可能希望给初学jdbc的朋友带来一定的便利,这样也不枉我点点滴滴的记录。
随着对jdbc整理和学习的逐渐深入,发现原先使用orm框架时忽略了那么多的细节,这样在出现问题或者学习orm更加深入知识时则会显得力不从心,在本文档将jdbc如何入门阐述清楚之后,增加了如下的内容:
Ø数据库连接池,以及常用连接池的使用(dbcp,c3p0等)
Ø编写一套基于jdbc轻量级的api,方便使用;
Ø如何将查询结果封装为对象;
Ø如何将查询结果封装为Map;
Ø如何将查询结果封装为List;
Ø如何在JDBC的使用中加入策略,模板等模式;
Ø在后面的JDBC高级部分将会讲解到Dbutils源码,Spring对JDBC的强大封装
第二节jdbc的概念
2.1概念
我最不喜欢替别人整理某个名词的概念了,只要是概念性的东西基本上在任何地方都可以查得到,所以我就通俗的写一些自己对jdbc的理解,所谓jdbc就是java与数据库之间进行通讯的api,也就是一个标准,所以如果一个java应用程序想要和数据库打交道基本上都离不开jdbc,众所周知,一些优秀的orm框架的底层也是采用jdbc进行封装的。
2.2Jdbc与应用程序的关系
JdbcAPI所处的位置和它与应用程序之间的关系,下面的一张图再也明显不过了,其中绿色的部分代表jdbcAPI,它提供了很多接口,并且本身也实现了很多方法,可以看到蓝色的部分就是各个数据库厂商自己对jdbcAPI的一些实现,这就是我们常见的数据库连接驱动,这是使用jdbc程序进行开发必不可少的东西。
2.3数据库的连接步骤
1.注册驱动(Driver)
2.建立连接(创建Connection)
3.创建执行sql语句(通常是创建Statement或者其子类)
4.执行语句
5.处理执行结果(在非查询语句中,该步骤是可以省略的)
6.释放相关资源
在后文中,将会对上述几个步骤一一进行讲解,希望读者能够仔细阅读;
2.4QuickStart
好了,了解了一下jdbc的基本概念,相比对jdbc已经有了一个感性的认识,现在我们为了直观期间,直接来上一段代码了解一下jdbc最简单的程序如何进行开发的。
在该小节中,我们以一个简单的增删改查为例进行说明,然后会将该章节中涉及的各个常用以及关键的API进行详细的讲解;
首先我们创建一个数据表,在test数据库下,见表语句为
createtableuser(idintegerprimarykey,
namevarchar(30),
birthdaydate,
moneyfloat);
插入两条语句
●insertintouservalues(2,'zhangsan','2010-01-01',15000);
●insertintouservalues(1,'wangwenjun','1984-06-09',8500.00);
好了,数据准备好了,我们通过一个完整的例子讲上述中数据库的连接步骤进行一个演示,在本例子中,初学者可能有些地方会觉得陌生,看不明白,不用着急,在后文中会对涉及的知识点逐个进行讲解
@Test
publicvoidwholeExample(){
try{
//1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2.获取数据库连接
Connectionconn=DriverManager.getConnection("jdbc:
mysql:
//localhost:
3306/test","root","r66t");
//3.创建执行句柄
Statementstmt=conn.createStatement();
//4.执行sql语句
ResultSetrs=stmt.executeQuery("select*fromuser");
//5.处理执行结果
while(rs.next()){
System.out.println("id:
"+rs.getInt
(1)+"\tname:
"+rs.getString
(2)+"\tbirthday:
"+rs.getDate(3)+"\tmoney:
"+rs.getFloat(4));
}
//6.释放资源
rs.close();
stmt.close();
conn.close();
}catch(SQLExceptione){
e.printStackTrace();
}catch(ClassNotFoundExceptione){
e.printStackTrace();
}
}
执行结果如下
id:
1name:
wangwenjunbirthday:
1984-06-09money:
8500.0
id:
2name:
zhangsanbirthday:
2010-01-01money:
15000.0
第三节如何与数据库建立连接
3.1注册驱动
●第一种注册方式
通常来说,注册驱动的方式有三种,下面我们将一一进行介绍,首先来看看直接调用DriverManager的registerDriver方法进行加载驱动,在本文中所有的程序均是在mysql数据库上进行演示的。
示例代码如下
@Test
publicvoidregistDriver1(){
try{
DriverManager.registerDriver(newcom.mysql.jdbc.Driver());
Connectionconn=DriverManager.getConnection("jdbc:
mysql:
//localhost:
3306/test","root","r66t");
Assert.assertEquals(false,conn.isClosed());
}catch(SQLExceptione){
e.printStackTrace();
}
}
执行结果为
可以看到,当前我们的程序与数据库的连接是正常的。
●第二种注册方式
@Test
publicvoidregistDriver2(){
try{
System.setProperty("jdbc.drivers","com.mysql.jdbc.Driver");
Connectionconn=DriverManager.getConnection("jdbc:
mysql:
//localhost:
3306/test","root","r66t");
Assert.assertEquals(false,conn.isClosed());
}catch(SQLExceptione){
e.printStackTrace();
}
}
执行结果为
可以看到,当前我们的程序与数据库的连接是正常的。
●第三种注册方式
@Test
publicvoidregistDriver3(){
try{
Class.forName("com.mysql.jdbc.Driver");
Connectionconn=DriverManager.getConnection("jdbc:
mysql:
//localhost:
3306/test","root","r66t");
Assert.assertEquals(false,conn.isClosed());
}catch(SQLExceptione){
e.printStackTrace();
}catch(ClassNotFoundExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
}
执行结果为
可以看到,当前我们的程序与数据库的连接是正常的。
一般来说注册驱动的方式大致上有上述三个,但是最常用的是最后一个,通过我们的代码演示可以看出,数据库都是完全可以被访问成功的。
3.2建立数据库的连接
其实在上文中的代码演示中,我们都会看到如何获取一个数据库连接,就是通过DriverManager.getConnection()方法获取数据库的链接,该方法大致有三个重载的方法,都是可以进行数据库连接的获取的,下面我们将会一一进行演示
StaticConnection
getConnection(String url)
试图建立到给定数据库URL的连接。
staticConnection
getConnection(String url,Properties info)
试图建立到给定数据库URL的连接。
staticConnection
getConnection(String url,Stringuser,String password)试图建立到给定数据库URL的连接。
●getConnection(String url)
该实例中,登录数据库的所有信息都编写在url中,实例代码如下
@Test
publicvoidgetConn1(){
try{
Class.forName("com.mysql.jdbc.Driver");
Connectionconn=DriverManager.getConnection("jdbc:
mysql:
//localhost:
3306/test?
user=root&password=r66t");
Assert.assertEquals(false,conn.isClosed());
}catch(SQLExceptione){
e.printStackTrace();
}catch(ClassNotFoundExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
}
●getConnection(String url,Properties info)
该方法则是将用户名和密码的信息存放在一个Properties键值对中,示例代码如下
@Test
publicvoidgetConn2(){
try{
Class.forName("com.mysql.jdbc.Driver");
Propertiesprops=newProperties();
props.put("user","root");
props.put("password","r66t");
Connectionconn=DriverManager.getConnection("jdbc:
mysql:
//localhost:
3306/test",props);
Assert.assertEquals(false,conn.isClosed());
}catch(SQLExceptione){
e.printStackTrace();
}catch(ClassNotFoundExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
}
●getConnection(String url,Stringuser,String password)
该方法则是我们在上文中演示了很多次的方式,也是最常用的一种方式,在这里再次进行一下赘述
@Test
publicvoidgetConn3(){
try{
Class.forName("com.mysql.jdbc.Driver");
Connectionconn=DriverManager.getConnection("jdbc:
mysql:
//localhost:
3306/test","root","r66t");
Assert.assertEquals(false,conn.isClosed());
}catch(SQLExceptione){
e.printStackTrace();
}catch(ClassNotFoundExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
}
3.3规范QuickStart中的例子
其中,我们在QuickStart中写了一个较为完整的代码示例,但是在该代码中存在很多的问题,我们通过本节的介绍,一一进行规范和优化,并且说明一下优化的好处是什么
使用数据库时,涉及数据库的资源都是非常奇缺的,我们在使用的过程中务必保证我们将使用过的资源释放,供别人再次使用或者自己下次再次使用,还有,创建数据库连接时可能存在各种各样的问题导致数据库连接获取失败,这个时候你的应用应该有义务告知上一层使用者到底出现了什么问题,这样就需要一个异常传递的过程(异常是一个比较复杂的机制,笔者在另一篇文章中有详细的讲解,希望读者能够关注)
@Test
publicvoidregularWhole()throwsException{//抛出异常
Connectionconn=null;
Statementstmt=null;
ResultSetrs=null;
try{
//1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2.获取数据库连接
conn=DriverManager.getConnection("jdbc:
mysql:
//localhost:
3306/test","root","r66t");
//3.创建执行句柄
stmt=conn.createStatement();
//4.执行sql语句
rs=stmt.executeQuery("select*fromuser");
//5.处理执行结果
while(rs.next()){
System.out.println("id:
"+rs.getInt
(1)+"\tname:
"+rs.getString
(2)+"\tbirthday:
"+rs.getDate(3)+"\tmoney:
"+rs.getFloat(4));
}
}finally{
try{
//6.释放资源
if(null!
=rs){
rs.close();
}
if(null!
=stmt){
stmt.close();
}
if(null!
=conn){
conn.close();
}
}finally{
if(null!
=rs){
rs.close();
}
if(null!
=stmt){
stmt.close();
}
if(null!
=conn){
conn.close();
}
}
}
}
在该实例中,可以看出确保了资源的完全释放,也将异常抛出告知上一层使用者,那块出现了问题,但是可以看到代码明显写的很罗嗦,而且有很多地方还是值得考究的
其中,注册驱动,数据库的驱动注册,只需要一次即可,重复注册是没有任何意义的,并且资源的释放,在每次使用的时候都进行资源的释放(写资源释放的代码)显得非常罗嗦,所以我们进行再一次的一个优化,代码如下
packagecom.wangwenjun.jdbc;
importjava.sql.Connection;
importjava.sql.DriverManager;
importjava.sql.ResultSet;
importjava.sql.SQLException;
importjava.sql.Statement;
publicfinalclassConnCreate{
static{
try{
Class.forName("com.mysql.jdbc.Driver");
}catch(ClassNotFoundExceptione){
e.printStackTrace();
}
}
publicstaticConnectiongetConnection(Stringurl,Stringuser,Stringpwd){
Connectionconn=null;
try{
conn=DriverManager.getConnection(url,user,pwd);
}catch(SQLExceptione){
e.printStackTrace();
}
returnconn;
}
publicstaticvoidclose(Connectionconn,Statementstmt,ResultSetrs)
throwsSQLException{
if(null!
=rs){
rs.close();
}
if(null!
=stmt){
stmt.close();
}
if(null!
=conn){
conn.close();
}
}
}
可以看出,驱动只会被注册一次,并且对资源释放的代码进行了抽取,在以后的使用过程中则会简单许多,当然上述的代码如果还需要追究问题,肯定还是存在的,在接下来的章节中我们也会进行深入的说明。
第四节Statement接口的使用详解
Statement是应用与数据库打交道最关键的一个接口,该接口包括了我们常用的CRUD操作,还可以设置抓取策略,比如设置数据库的游标是多少,可以根据数据量进行调优,也可以进行批量处理等,总之,该接口是非常关键的一个接口,包括后文中的预处理命令接口以及执行存储过程的接口。
4.1Statement的常用方法
下面的列表是从jdkAPI文档上粘贴出来的,当然很多方法我们并不是都能碰到,但是了解一下还是会有好处的
方法摘要
void
addBatch(String sql)
将给定的SQL命令添加到此Statement对象的当前命令列表中。
void
cancel()
如果DBMS和驱动程序都支持中止SQL语句,则取消此Statement对象。
void
clearBatch()
清空此Statement对象的当前SQL命令列表。
void
clearWarnings()
清除在此Statement对象上报告的所有警告。
void
close()
立即释放此Statement对象的数据库和JDBC资源,而不是等待该对象自动关闭时发生此操作。
boolean
execute(String sql)
执行给定的SQL语句,该语句可能返回多个结果。
boolean
execute(String sql,int autoGeneratedKeys)
执行给定的SQL语句(该语句可能返回多个结果),并通知驱动程序所有自动生成的键都应该可用于检索。
boolean
execute(String sql,int[] columnIndexes)
执行给定的SQL语句(该语句可能返回多个结果),并通知驱动程序在给定数组中指示的自动生成的键应该可用于检索。
boolean
execute(String sql,String[] columnNames)
执行给定的SQL语句(该语句可能返回多个结果),并通知驱动程序在给定数组中指示的自动生成的键应该可用于检索。
int[]
executeBatch()
将一批命令提交给数据库来执行,如果全部命令执行成功,则返回更新计数组成的数组。
ResultSet
executeQuery(String sql)
执行给定的SQL语句,该语句返回单个ResultSet对象。
int
executeUpdate(String sql)
执行给定SQL语句,该语句可能为INSERT、UPDATE或DELETE语句,或者不返回任何内容的SQL语句(如SQLDDL语句)。
int
executeUpdate(String sql,int autoGeneratedKeys)
执行给定的SQL语句,并用给定标志通知驱动程序由此Statement生成的自动生成键是否可用于检索。
int
executeUpdate(String sql,int[] columnIndexes)
执行给定的SQL语句,并通知驱动程序在给定数组中指示的自动生成的键应该可用于检索。
int
executeUpdate(String sql,String[] columnNames)
执行给定的SQL语句,并通知驱动程序在给定数组中指示的自动生成的键应该可用于检索。
Connection
getConnection()
检索生成此Statement对象的Connection对象。
int
getFetchDirection()
检索从数据库表获取行的方向,该方向是根据此Statement对象生成的结
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- JavaJDBC 学习 教程 由浅入深
![提示](https://static.bdocx.com/images/bang_tan.gif)