JDBC基础
JDBC
1簡(jiǎn)介
JDBC(Java DataBase Connectivity)是SUN公司提供的一組用于執(zhí)行SQL語(yǔ)句的Java API,它主要由接口組成??梢詾槎喾N關(guān)系數(shù)據(jù)庫(kù)提供統(tǒng)一訪問(wèn)。
Sun公司為簡(jiǎn)化數(shù)據(jù)庫(kù)開(kāi)發(fā),定義了一套JDBC接口,這套接口由數(shù)據(jù)庫(kù)廠商去實(shí)現(xiàn),這樣,開(kāi)發(fā)人員只需要學(xué)習(xí)JDBC接口,并通過(guò)JDBC加載具體的驅(qū)動(dòng),就可以操作數(shù)據(jù)庫(kù)。
組成JDBC的2個(gè)包: java.sql ?javax.sql
以上2個(gè)包已經(jīng)包含在J2SE中,所以不用導(dǎo)入,開(kāi)發(fā)這只需要導(dǎo)入JDBC的實(shí)現(xiàn)類即數(shù)據(jù)庫(kù)驅(qū)動(dòng)包。開(kāi)發(fā)JDBC應(yīng)用需要以上2個(gè)包的支持外,還需要導(dǎo)入相應(yīng)JDBC的數(shù)據(jù)庫(kù)實(shí)現(xiàn)(即數(shù)據(jù)庫(kù)驅(qū)動(dòng))。
2采用JDBC訪問(wèn)數(shù)據(jù)庫(kù)的基本步驟:
????A.載入JDBC DriverManager 驅(qū)動(dòng)程序
注冊(cè)數(shù)據(jù)庫(kù)驅(qū)動(dòng)兩種方式:
DriverManager.registerDriver(newDriver())
Class.forName(“數(shù)據(jù)庫(kù)廠商提供的驅(qū)動(dòng)類”);?? 推薦
????B.定義連接URL
jdbc:oracle:thin:? @127.0.01:1521:orcl
(1)JDBC協(xié)議:JDBC URL中的協(xié)議總是jdbc。
(2)<子協(xié)議>:驅(qū)動(dòng)程序名或數(shù)據(jù)庫(kù)連接機(jī)制的名稱
(3)<子名稱>:種標(biāo)識(shí)數(shù)據(jù)庫(kù)的方法。
????C.建立Connection連接
DriverManager.getConnection獲取連接
????D.創(chuàng)建Statement對(duì)象
createStatement():創(chuàng)建向數(shù)據(jù)庫(kù)發(fā)送sql的statement對(duì)象。
prepareStatement(sql):創(chuàng)建向數(shù)據(jù)庫(kù)發(fā)送預(yù)編譯sql的PrepareSatement對(duì)象。
prepareCall(sql):創(chuàng)建執(zhí)行存儲(chǔ)過(guò)程的CallableStatement對(duì)象。
setAutoCommit(boolean?autoCommit):設(shè)置事務(wù)是否自動(dòng)提交。
commit():在鏈接上提交事務(wù)。
rollback():在此鏈接上回滾事務(wù)。
?
E.執(zhí)行SQL查詢或更新
executeQuery(String?sql):用于向數(shù)據(jù)發(fā)送查詢語(yǔ)句。
executeUpdate(String?sql):用于向數(shù)據(jù)庫(kù)發(fā)送insert、update或delete語(yǔ)句
execute(Stringsql):用于向數(shù)據(jù)庫(kù)發(fā)送任意sql語(yǔ)句
addBatch(String?sql):把多條sql語(yǔ)句放到一個(gè)批處理中。
executeBatch():向數(shù)據(jù)庫(kù)發(fā)送一批sql語(yǔ)句執(zhí)行。
????F. 返回ResultSet結(jié)果處理
ResultSet還提供了對(duì)結(jié)果集進(jìn)行滾動(dòng)的方法:
??? next():?????????? 移動(dòng)到下一行
??? previous():?????? 移動(dòng)到前一行
??? absolute(int row): 移動(dòng)到指定行
??? beforeFirst():??? 移動(dòng)resultSet的最前面。
??? afterLast() : 移動(dòng)到resultSet的最后面
????G.關(guān)閉連接
??????????? 在關(guān)閉數(shù)據(jù)庫(kù)連接時(shí)應(yīng)該以ResultSet、Statement、Connection的順序進(jìn)行
3增刪改查
? Jdbc中的statement對(duì)象用于向數(shù)據(jù)庫(kù)發(fā)送SQL語(yǔ)句,想完成對(duì)數(shù)據(jù)庫(kù)的增刪改查,只需要通過(guò)這個(gè)對(duì)象向數(shù)據(jù)庫(kù)發(fā)送增刪改查語(yǔ)句即可。
Statement對(duì)象的executeUpdate方法,用于向數(shù)據(jù)庫(kù)發(fā)送增、刪、改的sql語(yǔ)句,executeUpdate執(zhí)行完后,將會(huì)返回一個(gè)整數(shù)(即增刪改語(yǔ)句導(dǎo)致了數(shù)據(jù)庫(kù)幾行數(shù)據(jù)發(fā)生了變化)。
Statement.executeQuery方法用于向數(shù)據(jù)庫(kù)發(fā)送查詢語(yǔ)句,executeQuery方法返回代表查詢結(jié)果的ResultSet對(duì)象。
4PreparedStatement
SQL注入是用戶利用某些系統(tǒng)沒(méi)有對(duì)輸入數(shù)據(jù)進(jìn)行充分的檢查,從而進(jìn)行惡意破壞的行為。
1、statement存在sql注入攻擊問(wèn)題,例如登陸用戶名采用' or 1=1 or name=‘
2、對(duì)于防范 SQL 注入,可以采用PreparedStatement取代Statement。
PreperedStatement是Statement的子接口,它的實(shí)例對(duì)象可以通過(guò)調(diào)用Connection.preparedStatement()方法獲得,相對(duì)于Statement對(duì)象而言:
?? 1. 【程序安全】 PreperedStatement可以避免SQL注入的問(wèn)題。
?? 2. 【執(zhí)行效率】 Statement會(huì)使數(shù)據(jù)庫(kù)頻繁編譯SQL,可能造成數(shù)據(jù)庫(kù)緩沖區(qū)溢出。PreparedStatement 可對(duì)SQL進(jìn)行預(yù)編譯,從而提高數(shù)據(jù)庫(kù)的執(zhí)行效率。
?????? < 對(duì)于整個(gè)DB中,只要預(yù)編譯的語(yǔ)句語(yǔ)法和緩存中匹配.那么在任何時(shí)候就可以不需要再次編譯而可以直接執(zhí)行.而statement的語(yǔ)句中,即使是相同一操作,而由于每次操作的數(shù)據(jù)不同所以使整個(gè)語(yǔ)句相匹配的機(jī)會(huì)極小,幾乎不太可能匹配 >
?
?? 3. 【開(kāi)發(fā)效率】并且PreperedStatement對(duì)于sql中的參數(shù),允許使用占位符的形式進(jìn)行替換,簡(jiǎn)化sql語(yǔ)句的編寫。
5使用事務(wù)
當(dāng)JDBC程序向數(shù)據(jù)庫(kù)獲得一個(gè)Connection對(duì)象時(shí),默認(rèn)情況下這個(gè)Connection對(duì)象會(huì)自動(dòng)向數(shù)據(jù)庫(kù)提交在它上面發(fā)送的SQL語(yǔ)句。若想關(guān)閉這種默認(rèn)提交方式,讓多條SQL在一個(gè)事務(wù)中執(zhí)行,可使用下列語(yǔ)句:
Connection.setAutoCommit(false);start transaction
Connection.rollback();? rollback
Connection.commit();? commit
6事務(wù)的特性
原子性(Atomicity)是指事務(wù)是一個(gè)不可分割的工作單位,事務(wù)中的操作要么都發(fā)生,要么都不發(fā)生。?
?
一致性(Consistency)事務(wù)必須使數(shù)據(jù)庫(kù)從一個(gè)一致性狀態(tài)變換到另外一個(gè)一致性狀態(tài)。
?
隔離性(Isolation)事務(wù)的隔離性是多個(gè)用戶并發(fā)訪問(wèn)數(shù)據(jù)庫(kù)時(shí),數(shù)據(jù)庫(kù)為每一個(gè)用戶開(kāi)啟的事務(wù),不能被其他事務(wù)的操作數(shù)據(jù)所干擾,多個(gè)并發(fā)事務(wù)之間要相互隔離。
?
持久性(Durability)持久性是指一個(gè)事務(wù)一旦被提交,它對(duì)數(shù)據(jù)庫(kù)中數(shù)據(jù)的改變就是永久性的,接下來(lái)即使數(shù)據(jù)庫(kù)發(fā)生故障也不應(yīng)該對(duì)其有任何影響。
7事務(wù)的隔離級(jí)別
多個(gè)線程開(kāi)啟各自事務(wù)操作數(shù)據(jù)庫(kù)中數(shù)據(jù)時(shí),數(shù)據(jù)庫(kù)系統(tǒng)要負(fù)責(zé)隔離操作,以保證各個(gè)線程在獲取數(shù)據(jù)時(shí)的準(zhǔn)確性。
如果不考慮隔離性,可能會(huì)引發(fā)如下問(wèn)題:
臟讀(dirty reads)
一個(gè)事務(wù)讀取了另一個(gè)未提交的并行事務(wù)寫的數(shù)據(jù)。
不可重復(fù)讀(non-repeatable reads)
一個(gè)事務(wù)重新讀取前面讀取過(guò)的數(shù)據(jù),發(fā)現(xiàn)該數(shù)據(jù)已經(jīng)被另一個(gè)已提交的事務(wù)修改過(guò)。
幻讀(phantom read)
一個(gè)事務(wù)重新執(zhí)行一個(gè)查詢,返回一套符合查詢條件的行,發(fā)現(xiàn)這些行因?yàn)槠渌罱峤坏氖聞?wù)而發(fā)生了改變
? 設(shè)置一個(gè)事務(wù)的隔離級(jí)別
?? set?transaction? isolation? level?read? committed ;
?? set?transaction? isolation? level?serializable ;
?? set?transaction? read? only ;
設(shè)置增個(gè)會(huì)話的隔離級(jí)別
?? alter session set isolation_levelserializable
?? alter session SET isolation_level READcommitted
8CallableStatement
CallableStatement是PreparedStatement的子接口,用于執(zhí)行 SQL 存儲(chǔ)過(guò)程。
JDBC執(zhí)行存儲(chǔ)過(guò)程的四種情況
[1]、只有輸入IN參數(shù),沒(méi)有輸出OUT參數(shù)
[2]、既有輸入IN參數(shù),也有輸出OUT參數(shù),輸出是簡(jiǎn)單值(非列表)
[3]、既有輸入IN參數(shù),也有輸出OUT參數(shù),輸出是列表
[4]、輸入輸出參數(shù)是同一個(gè)(INOUT)
9使用JDBC進(jìn)行批處理
業(yè)務(wù)場(chǎng)景:當(dāng)需要向數(shù)據(jù)庫(kù)發(fā)送一批SQL語(yǔ)句執(zhí)行時(shí),應(yīng)避免向數(shù)據(jù)庫(kù)一條條的發(fā)送執(zhí)行,而應(yīng)采用JDBC的批處理機(jī)制,以提升執(zhí)行效率。
實(shí)現(xiàn)批處理有兩種方式,
第一種方式:Statement.addBatch(sql)
?? 執(zhí)行批處理SQL語(yǔ)句
?? executeBatch()方法:執(zhí)行批處理命令
?? clearBatch()方法:清除批處理命令
優(yōu)點(diǎn):可以向數(shù)據(jù)庫(kù)發(fā)送多條不同的SQL語(yǔ)句。
缺點(diǎn):SQL語(yǔ)句沒(méi)有預(yù)編譯。當(dāng)向數(shù)據(jù)庫(kù)發(fā)送多條語(yǔ)句相同,但僅參數(shù)不同的SQL語(yǔ)句時(shí),需重復(fù)寫上很多條SQL語(yǔ)句。
第二種方式:? PreparedStatement.addBatch()
優(yōu)點(diǎn):發(fā)送的是預(yù)編譯后的SQL語(yǔ)句,執(zhí)行效率高。
缺點(diǎn):只能應(yīng)用在SQL語(yǔ)句相同,但參數(shù)不同的批處理中。因此此種形式的批處理經(jīng)常用于在同一個(gè)表中批量插入數(shù)據(jù),或批量更新表的數(shù)據(jù)。
10O-R Mapping簡(jiǎn)介
常用O-R Mapping映射工具
??? Hibernate Ibatis、Mybatis? Commons DbUtils(只是對(duì)JDBC簡(jiǎn)單封裝)
11CommonsDbUtils是Apache組織提供的一個(gè)對(duì)JDBC進(jìn)行簡(jiǎn)單封裝的開(kāi)源工具類庫(kù),使用它能夠簡(jiǎn)化JDBC應(yīng)用程序的開(kāi)發(fā),同時(shí)也不會(huì)影響程序的性能
DBUtils是java編程中的數(shù)據(jù)庫(kù)操作實(shí)用工具,小巧簡(jiǎn)單實(shí)用,需要項(xiàng)目導(dǎo)入commons-dbutils-1.6.jar才能夠正常使用DBUtils工具。
特征:
? 1.對(duì)于數(shù)據(jù)表的讀操作,他可以把結(jié)果轉(zhuǎn)換成List,Array,Set等java集合,便于程序員操作;
? 2.對(duì)于數(shù)據(jù)表的寫操作,也變得很簡(jiǎn)單(只需寫sql語(yǔ)句)
? 3.可以使用數(shù)據(jù)源,使用JNDI,數(shù)據(jù)庫(kù)連接池等技術(shù)來(lái)優(yōu)化性能--重用已經(jīng)構(gòu)建好的數(shù)據(jù)庫(kù)連接對(duì)象
Dbutils三個(gè)核心功能介紹
?????? QueryRunner中提供對(duì)sql語(yǔ)句操作的API.
? ? ?update(Connection conn, String sql, Object... params) ,用來(lái)完成表數(shù)據(jù)的增加、刪除、更新操作
? ? ?query(Connection conn, String sql,ResultSetHandler<T> rsh, Object... params) ,用來(lái)完成表數(shù)據(jù)的查詢操作
? ? ?ResultSetHandler接口,用于定義select操作后,怎樣封裝結(jié)果集.
?????? DbUtils類,它就是一個(gè)工具類,定義了關(guān)閉資源與事務(wù)處理的方法
12連接池技術(shù)
連接池是創(chuàng)建和管理一個(gè)連接的緩沖池的技術(shù),這些連接準(zhǔn)備好被任何需要它們的線程使用。數(shù)據(jù)庫(kù)連接池負(fù)責(zé)分配、管理和釋放數(shù)據(jù)庫(kù)連接,它允許應(yīng)用程序重復(fù)使用一個(gè)現(xiàn)有的數(shù)據(jù)庫(kù)連接,而不是再重新建立一個(gè);釋放空閑時(shí)間超過(guò)最大空閑時(shí)間的數(shù)據(jù)庫(kù)連接,來(lái)避免因?yàn)闆](méi)有釋放數(shù)據(jù)庫(kù)連接而引起的數(shù)據(jù)庫(kù)連接遺漏。
連接池技術(shù)的核心思想是:連接復(fù)用,通過(guò)建立一個(gè)數(shù)據(jù)庫(kù)連接池以及一套連接使用、分配、管理策略,使得該連接池中的連接可以得到高效、安全的復(fù)用,避免了數(shù)據(jù)庫(kù)連接頻繁建立、關(guān)閉的開(kāi)銷。
連接池主要由三部分組成:
?連接池的建立、連接池中連接的使用管理、連接池的關(guān)閉。
優(yōu)點(diǎn):
1資源重用:
由于數(shù)據(jù)庫(kù)連接得以重用,避免了頻繁創(chuàng)建,釋放連接引起的大量性能開(kāi)銷。在減少系統(tǒng)消耗的基礎(chǔ)上,另一方面也增加了系統(tǒng)運(yùn)行環(huán)境的平穩(wěn)性。
2更快的系統(tǒng)反應(yīng)速度
數(shù)據(jù)庫(kù)連接池在初始化過(guò)程中,往往已經(jīng)創(chuàng)建了若干數(shù)據(jù)庫(kù)連接置于連接池中備用。此時(shí)連接的初始化工作均已完成。對(duì)于業(yè)務(wù)請(qǐng)求處理而言,直接利用現(xiàn)有可用連接,避免了數(shù)據(jù)庫(kù)連接初始化和釋放過(guò)程的時(shí)間開(kāi)銷,從而減少了系統(tǒng)的響應(yīng)時(shí)間
3新的資源分配手段
對(duì)于多應(yīng)用共享同一數(shù)據(jù)庫(kù)的系統(tǒng)而言,可在應(yīng)用層通過(guò)數(shù)據(jù)庫(kù)連接池的配置,實(shí)現(xiàn)某一應(yīng)用最大可用數(shù)據(jù)庫(kù)連接數(shù)的限制,避免某一應(yīng)用獨(dú)占所有的數(shù)據(jù)庫(kù)資源
4統(tǒng)一的連接管理,避免數(shù)據(jù)庫(kù)連接泄露
在較為完善的數(shù)據(jù)庫(kù)連接池實(shí)現(xiàn)中,可根據(jù)預(yù)先的占用超時(shí)設(shè)定,強(qiáng)制回收被占用連接,從而避免了常規(guī)數(shù)據(jù)庫(kù)連接操作中可能出現(xiàn)的資源泄露
現(xiàn)在很多WEB服務(wù)器(Weblogic, WebSphere , Jboss , Tomcat)都提供了DataSoruce的實(shí)現(xiàn),即連接池的實(shí)現(xiàn)。通常我們把DataSource的實(shí)現(xiàn),按其英文含義稱之為數(shù)據(jù)源,數(shù)據(jù)源中都包含了數(shù)據(jù)庫(kù)連接池的實(shí)現(xiàn)。
?
也有一些開(kāi)源組織提供了數(shù)據(jù)源的獨(dú)立實(shí)現(xiàn):
DBCP數(shù)據(jù)庫(kù)連接池?? (tomcat)
C3P0數(shù)據(jù)庫(kù)連接池?? (hibernate、Spring)
c3p0與dbcp區(qū)別
dbcp沒(méi)有自動(dòng)回收空閑連接的功能
c3p0有自動(dòng)回收空閑連接功能
?
數(shù)據(jù)源(DataSource):
DataSource對(duì)象是獲取連接的首選方法, DriverManager 的替代項(xiàng)。
javax.sql.DataSource接口負(fù)責(zé)建立與數(shù)據(jù)庫(kù)的連接。
連接池中的連接對(duì)象是由該對(duì)象創(chuàng)建。
DataSource接口由驅(qū)動(dòng)程序供應(yīng)商實(shí)現(xiàn)
實(shí)現(xiàn) DataSource 接口的對(duì)象通常在基于JNDI而工作。
?
DBCP是 Apache 軟件基金組織下的開(kāi)源連接池實(shí)現(xiàn),該連接池依賴該組織下的另一個(gè)開(kāi)源系統(tǒng):Common-pool.如需使用該連接池實(shí)現(xiàn),應(yīng)在系統(tǒng)中增加如下三個(gè) jar 文件:
?? Commons-dbcp.jar:連接池的實(shí)現(xiàn)
?? Commons-pool.jar:連接池實(shí)現(xiàn)的依賴庫(kù)
?? Commons-logging-1.2.jar
Tomcat的連接池正是采用該連接池來(lái)實(shí)現(xiàn)的。該數(shù)據(jù)庫(kù)連接池既可以與應(yīng)用服務(wù)器整合使用,也可由應(yīng)用程序獨(dú)立使用
在Tomcat的context.xml文件配置
<Resource
? ??????name = "jdbc/java1709"
????? ??auth="Container"
????? ??type="javax.sql.DataSource"
????? ??username="??? "
????? ??password="??? "
????? ??maxActive ="100"
????? ??maxIdle="30"
????? ?? maxWait="10000"
????? ??driverClassName="oracle.jdbc.driver.OracleDriver"
????? ??url="jdbc:oracle:thin:@localhost:1521:orcl"
????? ??/>
總結(jié)
- 上一篇: iPhone屏幕各种尺寸分辨率(更新至X
- 下一篇: 1-2 三位数反转(算法竞赛入门经典)