JDBC课件.docx
《JDBC课件.docx》由会员分享,可在线阅读,更多相关《JDBC课件.docx(21页珍藏版)》请在冰豆网上搜索。
JDBC课件
JDBC
(JavaDatabaseConnectivity)
一、概述:
JDBC从物理结构上说就是Java语言访问数据库的一套接口集合。
从本质上来说就是调用者(程序员)和实现者(数据库厂商)之间的协议。
JDBC的实现由数据库厂商以驱动程序的形式提供。
JDBCAPI使得开发人员可以使用纯Java的方式来连接数据库,并进行操作。
ODBC:
基于C语言的数据库访问接口。
JDBC也就是Java版的ODBC。
JDBC的特性:
高度的一致性、简单性(常用的接口只有4、5个)。
1.在JDBC中包括了两个包:
java.sql和javax.sql。
java.sql基本功能。
这个包中的类和接口主要针对基本的数据库编程服务,如生成连接、执行语句以及准备语句和运行批处理查询等。
同时也有一些高级的处理,比如批处理更新、事务隔离和可滚动结果集等。
javax.sql扩展功能。
它主要为数据库方面的高级操作提供了接口和类。
如为连接管理、分布式事务和旧有的连接提供了更好的抽象,它引入了容器管理的连接池、分布式事务和行集等。
主要对象和接口:
注:
除了标出的Class,其它均为接口。
API
说明
java.sql.Connection
与特定数据库的连接(会话)。
能够通过getMetaData方法获得数据库提供的信息、所支持的SQL语法、存储过程和此连接的功能等信息。
代表了数据库。
java.sql.Driver
每个驱动程序类必需实现的接口,同时,每个数据库驱动程序都应该提供一个实现Driver接口的类。
java.sql.DriverManager
(Class)
管理一组JDBC驱动程序的基本服务。
作为初始化的一部分,此接口会尝试加载在”jdbc.drivers”系统属性中引用的驱动程序。
只是一个辅助类,是工具。
java.sql.Statement
用于执行静态SQL语句并返回其生成结果的对象。
java.sql.PreparedStatement
继承Statement接口,表示预编译的SQL语句的对象,SQL语句被预编译并且存储在PreparedStatement对象中。
然后可以使用此对象高效地多次执行该语句。
java.sql.CallableStatement
用来访问数据库中的存储过程。
它提供了一些方法来指定语句所使用的输入/输出参数。
java.sql.ResultSet
指的是查询返回的数据库结果集。
java.sql.ResultSetMetaData
可用于获取关于ResultSet对象中列的类型和属性信息的对象。
2、驱动程序按照工作方式分为四类:
1、JDBC-ODBCbridge+ODBC驱动
JDBC-ODBCbridge桥驱动将JDBC调用翻译成ODBC调用,再由ODBC驱动翻译成访问数据库命令。
优点:
可以利用现存的ODBC数据源来访问数据库。
缺点:
从效率和安全性的角度来说的比较差。
不适合用于实际项目。
2、基于本地API的部分Java驱动
我们应用程序通过本地协议跟数据库打交道。
然后将数据库执行的结果通过驱动程序中的Java部分返回给客户端程序。
优点:
效率较高。
缺点:
安全性较差。
3、纯Java的网络驱动
(中间协议)(本地协议)
appJDBC纯Java中间服务器DB
缺点:
两段通信,效率比较差
优点:
安全信较好
4、纯Java本地协议:
通过本地协议用纯Java直接访问数据库。
特点:
效率高,安全性好。
二、JDBC编程的步骤
注册一个driver
注册驱动程序有三种方式:
方式一:
Class.forName(“oracle.jdbc.driver.OracleDriver”);
JAVA规范中明确规定:
所有的驱动程序必须在静态初始化代码块中将驱动注册到驱动程序管理器中。
方式二:
Driverdrv=neworacle.jdbc.driver.OracleDriver();
DriverManager.registerDriver(drv);
方式三:
编译时在虚拟机中加载驱动
javac–Djdbc.drivers=oracle.jdbc.driver.OracleDriverxxx.java
java–Djdbc.drivers=驱动全名类名
使用系统属性名,加载驱动-D表示为系统属性赋值
附 :
mysql的Driver的全名com.mysql.jdbc.Driver
SQLServer的Driver的全名com.microsoft.jdbc.sqlserver.SQLServerDriver
建立连接
conn=DriverManager.getConnection(“jdbc:
oracle:
thin:
@192.168.0.20:
1521:
tarena”,”User”,”Pasword”);
Connection连接是通过DriverManager的静态方法getConnection(.....)来得到的,这个方法的实质是把参数传到实际的Driver中的connect()方法中来获得数据库连接的。
OracleURL的格式:
jdbc:
oracle:
thin:
(协议)@XXX.XXX.X.XXX:
XXXX(IP地址及端口号):
XXXXXXX(所使用的库名)
MySqlURL的写法 例:
jdbc:
mysql:
//192.168.8.21:
3306/test
获得一个Statement对象
sta=conn.createStatement();
通过Statement执行Sql语句
sta.executeQuery(Stringsql);返回一个查询结果集。
sta.executeUpdate(Stringsql);返回值为int型,表示影响记录的条数。
将sql语句通过连接发送到数据库中执行,以实现对数据库的操作。
处理结果集
使用Connection对象获得一个Statement,Statement中的executeQuery(Stringsql)方法可以使用select语句查询,并且返回一个结果集ResultSet通过遍历这个结果集,可以获得select语句的查寻结果,ResultSet的next()方法会操作一个游标从第一条记录的前面开始读取,直到最后一条记录。
executeUpdate(Stringsql)方法用于执行DDL和DML语句,比如可以update,delete操作。
只有执行select语句才有结果集返回。
例:
Statementstr=con.createStatement();//创建Statement
Stringsql=”insertintotest(id,name)values(1,”+”’”+”test”+”’”+”)”;
str.executeUpdate(sql);//执行Sql语句
Stringsql=”select*fromtest”;
ResultSetrs=str.executeQuery(Stringsql);//执行Sql语句,执行select语句后有结果集
next()如果有下一条记录返回true,否则为false;
有,则游标向下一条记录.
//遍历处理结果集信息
while(rs.next()){
System.out.println(rs.getInt(“id”));
System.out.println(rs.getString(“name”))
}
关闭数据库连接(释放资源)调用.close()
rs.close();sta.close();con.close();
ResultSetStatementConnection是依次依赖的。
注意:
要按先ResultSet结果集,后Statement,最后Connection的顺序关闭资源,因为Statement和ResultSet是需要连接时才可以使用的,所以在使用结束之后有可能其它的Statement还需要连接,所以不能现关闭Connection。
图形演绎编写JDBC程序的一般过程:
通过Driver
创建
DriverManager
创建
创建
Connection
Statement
ResultSet
①注册JDBC驱动程序;
②建立到DB连接;
③创建SQL语句;
④执行SQL语句;
⑤处理结果(有的话);
⑥与数据库断开连接。
SQL
数据
已经建立到DB连接
JDBC驱动程序
三、几个重要接口:
(1)Statement——SQL语句执行接口
Statement接口代表了一个数据库的状态,在向数据库发送相应的SQL语句时,都需要创建Statement接口或者PreparedStatement接口。
在具体应用中,Statement主要用于操作不带参数(可以直接运行)的SQL语句,比如删除语句、添加或更新。
(2)PreparedStatement:
预编译的Statement
第一步:
通过连接获得PreparedStatement对象,用带占位符(?
)的sql语句构造。
PreparedStatementpstm=con.preparedStatement(“select*fromtestwhereid=?
”);
第二步:
设置参数
pstm.setString(1,“ganbin”);
第三步:
执行sql语句
Rs=pstm.excuteQuery();
statement发送完整的Sql语句到数据库不是直接执行而是由数据库先编译,再运行。
而PreparedStatement是先发送带参数的Sql语句,再发送一组参数值。
如果是同构的sql语句,PreparedStatement的效率要比statement高。
而对于异构的sql则两者效率差不多。
同构:
两个Sql语句可编译部分是相同的,只有参数值不同。
异构:
整个sql语句的格式是不同的
注意点:
1、使用预编译的Statement编译多条Sql语句一次执行
2、可以跨数据库使用,编写通用程序
3、能用预编译时尽量用预编译
(3)ResultSet——结果集操作接口
ResultSet接口是查询结果集接口,它对返回的结果集进行处理。
ResultSet是程序员进行JDBC操作的必需接口。
(4)ResultSetMetaData——元数据操作接口
ResultSetMetaData是对元数据进行操作的接口,可以实现很多高级功能。
Hibernate运行数据库的操作,大部分都是通过此接口。
可以认为,此接口是SQL查询语言的一种反射机制。
ResultSetMetaData接口可以通过数组的形式,遍历数据库的各个字段的属性,对于我们开发者来说,此机制的意义重大。
JDBC通过元数据(MetaData)来获得具体的表的相关信息,例如,可以查询数据库中有哪些表,表有哪些字段,以及字段的属性等。
MetaData中通过一系列getXXX将这些信息返回给我们。
数据库元数据DatabaseMetaData使用connection.getMetaData()获得
MetaData包括:
包含了关于数据库整体元数据信息。
结果集元数据ResultSetMetaData使用resultSet.getMetaData()获得
比较重要的是获得表的列名、列数等信息。
结果集元数据对象:
ResultSetMetaDatameta=rs.getMetaData();
✓字段个数:
meta.getColomnCount();
✓字段名字:
meta.getColumnName();
✓字段JDBC类型:
meta.getColumnType();
✓字段数据库类型:
meta.getColumnTypeName();
数据库元数据对象:
DatabaseMetaDatadbmd=con.getMetaData();
数据库名=dbmd.getDatabaseProductName();
数据库版本号=dbmd.getDatabaseProductVersion();
数据库驱动名=dbmd.getDriverName();
数据库驱动版本号=dbmd.getDriverVersion();
数据库Url=dbmd.getURL();
该连接的登陆名=dbmd.getUserName();
四、JDBC异常处理:
JDBC中,和异常相关的两个类是SQLException和SQLWarning。
1.SQLException类:
用来处理较为严重的异常情况。
比如:
传输的SQL语句语法的错误;
JDBC程序连接断开;
SQL语句中使用了错误的函数。
SQLException提供以下方法:
getNextException()——用来返回异常栈中的下一个相关异常;
getErrorCode()——用来返回代表异常的整数代码(errorcode);
getMessage()——用来返回异常的描述信息(errormessage)。
2.SQLWarning类:
用来处理不太严重的异常情况,也就是一些警告性的异常。
其提供的方法和使用与SQLException基本相似。
结合异常的两种处理方式,明确何时采用哪种。
A.throws处理不了,或者要让调用者知道,就throws;
B.try…catch能自行处理,就进行异常处理。
五、JDBC中使用Transaction编程(事务编程)
1.事务是具备以下特征(ACID)的工作单元:
Ø原子性(Atomicity)——如果因故障而中断,则所有结果均被撤消;
Ø一致性(Consistency)——事务的结果保留不变;
Ø孤立性(Isolation)——中间状态对其它事务是不可见的;
Ø持久性(Durability)——已完成的事务结果上持久的。
原子操作,也就是不可分割的操作,必须一起成功一起失败。
2.事务处理三步曲:
(事务是一个边界)
connection.setAutoCommit(false);//把自动提交关闭
正常的DB操作//若有一条SQL语句失败了,自动回滚
mit()//主动提交
或connection.rollback()//主动回滚
完整的代码片段:
try{
con.setAutoCommit(false);//step①把自动提交关闭
Statementstm=con.createStatement();
stm.executeUpdate("insertintoperson(id,name,age)values(520,'X-Man',18)");
stm.executeUpdate("insertintoPerson(id,name,age)values(521,'Super',19)");
//step②正常的DB操作
mit();//step③成功主动提交
}catch(SQLExceptione){
try{
con.rollback();
}catch(Exceptione){e.printStackTrace();}//step③失败则主动回滚
}
3.JDBC事务并发产生的问题和事务隔离级别
JDBC事务并发产生的问题:
脏读(DirtyReads)一个事务读取了另一个并行事务还未提交的数据。
不可重复读(UnPrpeatableRead)一个事务再次读取之前的数据时,得到的数据不一致,被另一个已提交的事务修改。
幻读(PhantomRead)一个事务重新执行一个查询,返回的记录中包含了因为其它最近提交的事务而产生的新记录。
为了避免以上三种情况的出现,则采用
事务隔离级别:
TRANSACTION_NONE
不使用事务
TRANSACTION_READ_UNCOMMITTED
可以读取未提交数据
TRANSACTION_READ_COMMITTED
可以避免脏读,不能够读取没提交的数据,最常用的隔离级别大部分数据库的默认隔离级别
TRANSACTION_REPEATABLE_READ
可以避免脏读,重复读取
TRANSACTION_SERIALIZABLE
可以避免脏读,重复读取和幻读,(事务串行化)会降低数据库效率
以上的五个事务隔离级别都是在Connection类中定义的静态常量,使用setTransactionIsolation(intlevel)方法可以设置事务隔离级别。
比如:
con.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
六、JavaBean的定义:
1、是一个普通的Java类
2、在结构上没有预先的规定,不需要容器,不需要继承类或实现接口
3、要求必须放在包中,要求实现Serializable接口
4、要求有一个无参的构造方法.
5、属性的类型必须保持唯一,get方法返回值必须和set方法参数类型一致
6、对每个属性要有对应的get和set方法。
注:
隐藏属性可以没有
7、可以有外观作为显示控制,事件机制。
七、JDBC2.0新特性:
1、Scrollability结果集可滚动
滚动:
可双向支持绝对与相对滚动,对结果集可进行多次迭代。
Con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,
ResultSet.CONCUR_UPDATABLE);
TYPE_FORWARD_ONLY:
该常量指示指针只能向前移动的ResultSet对象的类型。
TYPE_SCROLL_SENSITIVE:
该常量指示可滚动并且通常受其他的更改影响的ResultSet对象的类型。
CONCUR_UPDATABLE:
该常量指示可以更新的ResultSet对象的并发模式。
绝对定位:
booleanabsolute(introw)将游标移动到指定位置。
相对定位:
voidafterLast()将游标向后移动一位。
voidbeforeFirst()。
将游标向前移动一位。
booleanfirst()将游标移动到结果集最前
booleanlast()将游标移动到结果集末尾。
2、Updatability结果集可更新。
(主要应用于桌面应用)
更新:
rs.updateString(“name”,”Tony”);
rs.updateInt(1,”122323”);修改
rs.deleteRow();删除
rs.updateRow();
注:
只有在必要的时候(如桌面应用)才用结果集更新数据库,因为使用结果集更新数据库效率低下。
可更新结果集还要看数据库驱动程序是否支持,如Oracle就支持MySql不支持。
并且只能针对一张表做结果集更新。
而且不能有join操作。
必须有主健,必须把非空没有默认值的字段查出。
处理可更新结果级时不能用select*来执行查询语句,必须指出具体要查询的字段。
3、Batchupdates可批量更新。
将一组对数据库的更新操作发送到数据库统一执行(数据库支持并发执行操作),以提高效率。
主要是通过减少数据(Sql语句或参数)在网络上传输的次数来节省时间。
(1)对于Statement的批量更新处理:
stm.addBatch(Sql);
stm.addBatch(Sql);
int[]results=stm.executeBatch();
(2)对于PreparedStatement的批量跟新处理
pstm.setInt(1,11);pstm.setString(2,”haha”);……..
pstm.addBatch()
pstm.setInt(1,12);pstm.setString(2,”gaga”);……..
pstm.addBatch()
int[]results=stm.executeBatch();
注:
int[]中每一个数表示该Sql语句影响到的记录条数。
PreparedStatement的更新操作比Statement的更新操作多了一个设置参数的过程。
八、SQL3.0规范中的新类型
Array数组类型,主要用于保存一些类似于数组结构的数据。
Sturct结构
Blob,大的二进制数据文件,最多存储2G。
Clob,大文本文件对象,最多存储2G。
在使用上述大对象的时候,在使用JDBC插入记录时要先插入一个空的占位对象,然后使用
selectblobdatafromt_blobwhereid="+id+"forupdate这样的语法来对获得的大对象,进行实际的写入操作Blod通过getBinaryOutputStream()方法获取流进行写入。
getBinaryStream()方法获得流来获取Blob中存储的数据。
Clob的操作也和、Blob相同。
getAsciiStream()方法用于读取存储的文本对象,getAsciiOutputStream()方法之获得流用来向文件对象写入的。
BLOB与CLOB的异同点:
都可以存储大量超长的数据;
BLOB(BinaryLargeObject)以二进制格式保存于数据库中,特别适合保存图片、视频文件、音频文件、程序文件等;
CLOB(CharacterLargeObject)以Character格式保存于数据库中,适合保存比较长的文本文件。
九、SQL数据类型及其相应的Java数据类型
SQL数据类型 Java数据类型 说明
---------------------------------------------------------------------------------------------------------------------------------------
INTEGER或者INT int 通常是个32位整数
SMALLINT short 通常是个16位整数
NUMBER(m,n) Java.sql.Numeric 合计位数是m的定点十进制数,小数后面有n位数
DECIMAL(m,n)同上
DEC(m,n) Java.sql.Nume