JDBC讲课流程.docx
《JDBC讲课流程.docx》由会员分享,可在线阅读,更多相关《JDBC讲课流程.docx(48页珍藏版)》请在冰点文库上搜索。
JDBC讲课流程
JDBC讲课流程
第一课
JDBC概述和基本数据库操作
JDBC(javadatabaseconnectivity)用于在java程序中实现数据库操作的数据库编程接口,支持基本的SQL语句,为应用程序和数据库之间提供了桥梁
java程序和数据库之间的关系如下图:
JDBC的版本:
介绍java中和操作数据库相关的API,解释这些API都是未实现的,真正实现操作的是数据库厂家提供的类库
。
开始数据库编程:
(别忘先导入包)
第一步加载数据库驱动程序
这是利用反射注册一个数据库驱动
或者用驱动管理器也可以注册数据库驱动
第二步创建数据库连接对象
Stringuser="scott";
Stringpwd="tiger";
Connectionconn=DriverManager.getConnection(url,user,pwd);
其中dhc表示的是数据库名或域名而并非是服务名
DriverManager类存有已注册的Driver类的清单。
当调用方法getConnection时,它将检查清单中的每个驱动程序,直到找到可与URL中指定的数据库进行连接的驱动程序为止。
如果改成用OCI形式连接,url字符串改为类似以下语句:
Stringurl="jdbc:
oracle:
oci8:
scott/tiger@dhc";
或者
Stringurl="jdbc:
oracle:
oci:
scott/tiger@dhc";
第三步创建SQL语句载体对象
第四步执行SQL语句返回结果集对象
第五步遍历结果集返回数据
while
System.out
}
在这一步讲解结果集指针的概念,默认状态下游标只能向下移动
需要注意getXXX方法的数据类型要和表中字段的数据类型兼容。
讲解getXXX()括号中的参数既可以是列索引,也可以是列名,如果使用列名并且结果集中有多个列的名字是相同的,那么返回第一列的的列值,一般用列索引效率会高一些
介绍rs.wasNull方法,当前最后一次getXXX()返回的列值是否为null,需要注意的是如果get方法以数字的形式获取列值且返回的列值为null,得到的结果会自动的转换为0或
别忘记在下面介绍java的数据类型和SQL的数据类型之间的映射关系
第六步关闭对象释放资源
采取逆向关闭对象的顺序
在关闭stmt对象或利用stmt对象重新执行其他SQL语句时时会自动关闭rs对象。
解讲数据类型之间的映射关系
SQL类型
JAVA类型
CHAR
String
REAL
Float
DATALINK
REF
Ref
STRUCT
Struct
DISTINCT
Mappingofunderlyingtype
ARRAY
Array
BLOB
Blob
CLOB
Clob
TIMESTAMP
TIME
DATE
LONGVARBINARY
byte[]
VARBINARY
byte[]
BINARY
byte[]
DOUBLE
double
FLOAT
double
VARCHAR
String
LONGVARCHAR
String
以上操作的完整代码:
publicclassJDBC1{
publicstaticvoidmain(String[]args)throwsSQLException{
//注册数据库驱动程序
//创建数据库连接对象
Stringuser="scott";
Stringpwd="tiger";
//创建SQL语句载体对象
//返回结果集对象
//遍历结果集返回数据
}
//关闭对象
}
}
经过优化的代码:
publicclassJDBC1{
publicstaticvoidmain(String[]args){
Connectionconn=null;
Statementstmt=null;
ResultSetrs=null;
try{
//注册数据库驱动程序
//创建数据库连接对象
Stringuser="scott";
Stringpwd="tiger";
//创建SQL语句载体对象
//返回结果集对象
//遍历结果集返回数据
}
}catch(SQLExceptione){
}finally{
try{
//关闭对象
if(rs!
=null)
if(stmt!
=null)
if(conn!
=null)
}catch(SQLExceptione){
}
}
}
}
练习:
查询departments表中的50~190号部门信息(部门编号,部门名称,部门管理者姓名,部门所在城市)
import
publicclassTest6{
publicstaticvoidmain(String[]args){
Connectionconn=null;
Statementstmt=null;
ResultSetrs=null;
try{
DriverManager.registerDriver(new
Stringurl="jdbc:
oracle:
thin:
@localhost:
1521:
dhc";
Stringuser="scott";
Stringpwd="tiger";
conn=DriverManager.getConnection(url,user,pwd);
rs=stmt
.executeQuery(9);
while
System.out""""
""
}
}catch(SQLExceptione){
}finally{
try{
if(rs!
=null)
if(stmt!
=null)
if(conn!
=null)
}catch(Exceptione){
}
}
}
}
综合练习:
查询job_history表中所有数据,将数据写入到文本文件中,一条记录一行,列值之间用|隔开
import
import
publicclassTest7{
publicstaticvoidmain(String[]args){
Connectionconn=null;
Statementstmt=null;
ResultSetrs=null;
FileWriterfw=null;
BufferedWriterbw=null;
try{
DriverManager.registerDriver(new
Stringurl="jdbc:
oracle:
thin:
@localhost:
1521:
dhc";
Stringuser="scott";
Stringpwd="tiger";
conn=DriverManager.getConnection(url,user,pwd);
stmt=conn.createStatement();
"select*fromjob_history");
fw=newFileWriter();
bw=newBufferedWriter(fw);
while
"|""|"
"|""|"
}
}catch(SQLExceptione){
}catch(IOExceptione){
}finally{
try{
if(bw!
=null)
if(rs!
=null)
if(stmt!
=null)
if(conn!
=null)
}catch(Exceptione){
}
}
}
}
第二课
数据增删改和可滚动结果集
讲述Statement对象执行SQL语句的三种方法:
executeQuery()执行查询单个结果集的语句,该语句返回单个ResultSet对象
executeUpdate()执行给定SQL语句,该语句可能为INSERT、UPDATE或DELETE语句,或者不返回任何内容的SQL语句(如SQLDDL语句),该语句返回影响的行数,如果是DDL语句则返回0
execute()执行给定的SQL语句,这个SQL语句可能实现并不知道是查询还是增删改,返回值是布尔值,如果是查询语句返回结果则为true,可以用getResultSet得到ResultSet结果
创建一个学生表做数据增删改试验:
createtableStudent
(
sidnumber,
snamevarchar2(50),
addDatedate
);
演示增加学生数据
publicclassTest8{
publicstaticvoidmain(String[]args){
Connectionconn=null;
Statementstmt=null;
try{
Stringurl="jdbc:
oracle:
thin:
@localhost:
1521:
dhc";
Stringuser="scott";
Stringpwd="tiger";
inti=stmt
.executeUpdate("insertintoStudentvalues(101,'tom',to_date('2008-3-1','yyyy-mm-dd'))");
}catch(SQLExceptione){
}finally{
try{
if(stmt!
=null)
if(conn!
=null)
}catch(Exceptione){
}
}
}
}
演示修改学生数据:
……
inti=stmt
.executeUpdate("updateStudentsetsname='jack',addDate=to_date('2007-3-1','yyyy-mm-dd')wheresid=101");
System.out.println("操作了"+i+"行");
……
学生自己动手改成删除101学生数据:
……
inti=stmt
.executeUpdate("deletefromStudentwheresid=101");
System.out.println("操作了"+i+"行");
……
学生试验执行DDL语句删除表:
……
inti=stmt
.executeUpdate("droptableStudent");
……
学生练习:
提供一个原始文本文件,将文本文件中的数据导入到数据库中的表中
101,tom,2008-3-1
102,jack,2008-3-2
103,rose,2008-3-3
104,smith,2008-3-4
105,john,2008-3-5
106,zhang,2008-3-6
107,li,2008-3-7
import
import
publicclassTest10{
publicstaticvoidmain(String[]args)throwsException{
Connectionconn=null;
Statementstmt=null;
ResultSetrs=null;
DriverManager.registerDriver(new
Stringurl="jdbc:
oracle:
thin:
@localhost:
1521:
dhc";
Stringuser="scott";
Stringpwd="tiger";
conn=DriverManager.getConnection(url,user,pwd);
TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_UPDATABLE);
FileReaderfr=newFileReader();
BufferedReaderbr=newBufferedReader(fr);
while(s!
=null){
",");
"insertintoStudentvalues("+rows[0]+",'"
+rows[1]+"',to_date('"+rows[2]+"','yyyy-mm-dd'))");
}
}
}
讲解可滚动的结果集游标指针
Connection对象创建Statement对象有两种形式:
●一种是用createStatement()无参方法,这种方法创建的Statement对象执行的查询的结果集指针只能向下移动
●另一种方法是用createStatement(intresultSetType,intresultSetConcurrency)有参方法,这种方法创建的Statement对象执行的查询结果集的指针是可以任意移动的
后一种方法有两个参数:
分别是结果集游标类型和结果集是否可更新
结果集游标类型有三个设置值:
1.指针只能向下移动(默认)
2.指针可任意滚动,但结果集中被更新的行不可视
3.指针可任意滚动,结果集中被更新的行可视
结果集是否可更新有两个设置值:
1.只读(默认)
2.可更新记录
关于指针移动的方法:
默认打开结果集的时候指针位于第一行记录的上面
next()下一行
previous()上一行
first()第一行
last()最后一行
absolute(n)定位到第n条
relative(n)相对于当前指针位置定位到第n条,n为正数下移,n为负数上移
beforeFirst()第一条的前面
afterLast()最后一条的后面
getRow()获得当前行的行号
学生练习:
查询出工资排名在第6位到第10位的员工编号,姓名和工资
……
TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
"select*fromemployeesorderbysalarydesc");
if
for(inti=6;i<=10;i++){
System.out.println(i+":
\t""/"
"/"
if
break;
}
}
……
学生练习2(选做):
每次执行程序都随机查询出1个员工的编号和姓名作为中奖名单,以前已经中过奖的员工不在抽奖的范围内
创建一个临时表存放中过奖的员工编号
createtableaward(employee_idnumber);
代码片断
TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
//查询出以前未抽过奖的所有员工
rs=stmt
.executeQuery("select*fromemployeeswhereemployee_idnotin(selectemployee_idfromaward)");
//获得员工总数
intempcount=0;
if
//产生随机数指针位置
intr=(int)((empcount-1+1)*Math.random()+1);
//指针定位打印出员工信息,并保存中奖员工编号
if
System.out.println("中奖员工:
""\t"
"insertintoawardvalues('"
+"')");
}else{
System.out.println("已经没有未中过奖的员工了");
}
将上例修改为每次执行程序抽出3个中奖员工,并且不能和已经抽出过的员工重复。
for(inti=1;i<=3;i++){
//查询出以前未抽过奖的所有员工
rs=stmt
.executeQuery("select*fromemployeeswhereemployee_idnotin(selectemployee_idfromaward)");
//获得员工总数
intempcount=0;
if
else
break;
//产生随机数指针位置
intr=(int)((empcount-1+1)*Math.random()+1);
//指针定位打印出员工信息,并保存中奖员工编号
if
System.out.println("中奖员工:
""\t"
"insertintoawardvalues('"
+"')");
}
}
第三课
元数据(Meta-Data)
Connection对象的getMetaData()方法返回DatabaseMetaData对象中包含了数据库信息
ResultSet对象的getMetaData()方法返ResultSetMetaData对象包含了结果集信息
演示获取数据库信息
//获得数据库元数据
//打印URL
System.out
//打印用户名
System.out
//打印JDBC驱动版本号
System.out
//打印数据库名称
System.out
//打印数据库版本号
System.out
演示获取结果集信息
"select*fromemployees");
//获取元数据
//打印列的个数
System.out.println("列数:
"
//第1列列名
System.out
//第1列数据类型
System.out
//第1列数据允许宽度
System.out
//第一列数据小数位数
System.out
学生练习:
打印出查询员工表结果集的数据结构,如下图
1EMPLOYEE_ID/NUMBER(6,0)
2FIRST_NAME/VARCHAR2(20,0)
3LAST_NAME/VARCHAR2(25,0)
4EMAIL/VARCHAR2(25,0)
5PHONE_NUMBER/VARCHAR2(20,0)
6HIRE_DATE/DATE(0,0)
7JOB_ID/VARCHAR2(10,0)
8SALARY/NUMBER(8,2)
9COMMISSION_PCT/NUMBER(2,2)
10MANAGER_ID/NUMBER(6,0)
11DEPARTMENT_ID/NUMBER(4,0)
"select*fromemployees");
//获取元数据
//循环输出列结构
for(int
System.out.print(i+"\t");
System.out"/");
System.out"(");
System.out","")");
System.out.println();
}
学生练习(选做):
输出scott用户下的所有的表结构,如下
……
表名:
AWARD
1EMPLOYEE_ID/NUMBER(0,-127)
-------------------------------------------
表名:
COUNTRIES
1COUNTRY_ID/CHAR(2,0)
2COUNTRY_NAME/VARCHAR2(40,0)
3REGION_ID/NUMBER(0,-127)
-------------------------------------------
表名:
STUDENT
1SID/NUMBER(0,-127)
2SNAME/VARCHAR2(50,0)
3ADDDATE/DATE(0,0)
-------------------------------------------
……
Statementstmt=null;
ResultSetrs=null;
Statementstmt2=null;
ResultSetrs2=null;
//创建SQL语句载体
//查询数据字典获得表名
"selecttable_namefromtabs");
//遍历表
while
//打印表名
System.out.println("表名:
"
//查询表的所有列
"select*from"
//获取元数据
//循环输出列结构
for(int
System.out.print(i+"\t");
System.out"/");
System.out"(");
System.out","")");
System.out.println();
}
System.out.println("-------------------------------------------");
}
第四课
预制SQL语句和已存储过程
PreparedStatement(预制SQL语句)继承了Statement,特点是预编译好SQL语句并存放在PreparedStatement对象中,适合在SQL语句中具有一个或多个输入参数,用做占位符,例如员工的编号,更新后的新工资,在语句执行之前用setXXX方法给参数赋值,如果是多条语句结构相同但是参数不同,用PreparedStatement速度会比Statement快。
还有一个好处是用占位符参数的形式不用考虑用户在设置参数的实参的时候无意中输入的SQL关键字,如单引号。
演示用预编译语句增加学生信息:
publicclassTest16{
publicstaticvoidmain(String[]args){
Connectionconn=null;
PreparedStatementpstmt=null;
try{
Stringurl="jdbc:
oracle:
thin:
@localhost:
1521:
dhc"