使用JDBC(API)來(lái)操作數(shù)據(jù)庫(kù)用到的類(lèi):
1 Connection 連接
2 Statement 語(yǔ)句
3 ResultSet 結(jié)果集
Connection
連接 相當(dāng)于Session 屈尼、Socket
連接Connection是接口^质ぁ!祭示!
A connection (session) with a specific database. SQL statements are executed and results are returned within the context of a connection.
(一個(gè)連接就是一個(gè)和指定數(shù)據(jù)庫(kù)的會(huì)話闲先,SQL語(yǔ)句被執(zhí)行并在連接的上下文中返回結(jié)果)
即首先要和服務(wù)器建立連接 然后發(fā)給其消息 服務(wù)器執(zhí)行后返回結(jié)果 通過(guò)連接來(lái)完成统抬!
A Connection object's database is able to provide information describing its tables, its supported SQL grammar, its stored procedures, the capabilities of this connection, and so on. This information is obtained with the getMetaData method.
一個(gè)連接對(duì)象能夠提供一些描述表的信息匪蝙、和它支持的SQL語(yǔ)句窟感、存儲(chǔ)過(guò)程吓著、連接的能力等鲤嫡,這些信息可以通過(guò)getMetaData(獲得元數(shù)據(jù))方法得到送挑。
注:元數(shù)據(jù)是描述數(shù)據(jù)的數(shù)據(jù)...
Connection對(duì)象創(chuàng)建方式:
Connection conn = DriverManager.getConnection(url, user, password);
即使用DiverManager(驅(qū)動(dòng)器管理器)的getConnection方法創(chuàng)建連接對(duì)象。
拓展:
驅(qū)動(dòng)器管理器 DiverManager
The basic service for managing a set of JDBC drivers.
是管理一系列JDBC驅(qū)動(dòng)的基本服務(wù)
來(lái)看getConnection函數(shù)參數(shù):
url:數(shù)據(jù)庫(kù)的url地址
user:數(shù)據(jù)庫(kù)賬號(hào)
password:數(shù)據(jù)庫(kù)密碼
注:
URL Uniform Resource Locator
統(tǒng)一資源定位符(是標(biāo)識(shí)符的一種)
(定位符是帶層級(jí)結(jié)構(gòu)的概念)
URI Uniform Resource Identifier
統(tǒng)一資源標(biāo)識(shí)符
注意:
url地址對(duì)不同的數(shù)據(jù)庫(kù)暖眼,格式不一樣惕耕!
對(duì)于MySQL數(shù)據(jù)庫(kù)格式:
String url = "jdbc:mysql://localhost:3306/itcast";
jdbc:mysql 叫協(xié)議 中間有:分割叫子協(xié)議
locakhost 為主機(jī)名
3306 為端口號(hào) port
itcast 為路徑path (一個(gè)數(shù)據(jù)庫(kù)名稱(chēng))
寫(xiě)全url 等并加入try - catch處理運(yùn)行:
顯示:No suitable driver found for jdbc:mysql://localhost:3306/itcast
(對(duì)于協(xié)議jdbc:mysql://localhost:3306/itcast找不到合適的驅(qū)動(dòng))
因?yàn)檫B接Connection是接口,光有接口的干不了事情的罢荡!必須要有實(shí)現(xiàn)類(lèi)赡突!
看Connection源代碼:
右擊查看層次視圖:(按F4也可)
可見(jiàn)根本沒(méi)有連接的實(shí)現(xiàn)類(lèi)
JDBC是API 是一套規(guī)范 這套API就是接口(規(guī)范一般都是接口) 接口 抽象類(lèi) 都是不具體的 而對(duì)于每個(gè)廠商又有自己產(chǎn)品的實(shí)現(xiàn) 所以每個(gè)廠商都得給出這個(gè)實(shí)現(xiàn) 那就是驅(qū)動(dòng)程序的作用 而驅(qū)動(dòng)程序需要去網(wǎng)上下載 即mysql-connector-java-5.x.x.jar 文件
在此給出一個(gè)版本的下載:
mysql-connector-java-5.1.30
將驅(qū)動(dòng)程序加到項(xiàng)目中:
先在java項(xiàng)目下新建lib文件夾
直接ctrl + c / v 把 mysql-connector-java-x.jar文件粘貼到lib文件夾下:
還要右擊把jar文件放到構(gòu)架路徑中去!G浴:
(即加入classpath中)
添加構(gòu)架路徑成功:
再看等級(jí)樹(shù) 有了實(shí)現(xiàn)類(lèi):
所以驅(qū)動(dòng)程序就是把這些規(guī)范加以實(shí)現(xiàn)
來(lái)看驅(qū)動(dòng)文件中的com.mysql.jdbc.Driver.class:
此Driver.class實(shí)現(xiàn)的是java.sql.Driver接口:
java.sql.Driver是驅(qū)動(dòng)器接口
java.sql.Driver javadoc:
javadoc中指出
The interface that every driver class must implement.
The Java SQL framework allows for multiple database drivers.
Each driver should supply a class that implements the Driver interface.
(以上英文很簡(jiǎn)單 自行閱讀)
The DriverManager will try to load as many drivers as it can find and then for any given connection request, it will ask each driver in turn to try to connect to the target URL.
(驅(qū)動(dòng)器管理器將嘗試去加載很多它能找到的或者通過(guò)給定的鏈接找到的驅(qū)動(dòng)器們惭缰,它將輪流請(qǐng)求每一個(gè)驅(qū)動(dòng)程序 并 試圖去連接到地址)
java doc重要的:
When a Driver class is loaded, it should create an instance of itself and register it with the DriverManager. This means that a user can load and register a driver by calling:
Class.forName("foo.bah.Driver")
當(dāng)驅(qū)動(dòng)程序類(lèi)被加載,它將去創(chuàng)建一個(gè)自身的實(shí)例并在驅(qū)動(dòng)器管理器中進(jìn)行注冊(cè)笼才,這意味著用戶(hù)可以通過(guò)調(diào)用 Class.forName("foo.bah.Driver") 函數(shù) 加載并注冊(cè)一個(gè)驅(qū)動(dòng)
Class.forName("foo.bah.Driver")用來(lái)注冊(cè)驅(qū)動(dòng)漱受!
所以在 提供JDBC連接的url、賬號(hào)骡送、密碼 和 創(chuàng)建數(shù)據(jù)庫(kù)的連接 之前需要 先加載JDBC的驅(qū)動(dòng)類(lèi):
Class.forName("com.mysql.jdbc.Driver");
"com.mysql.jdbc.Driver" 是 className
到此我們完成了:
第一步 加載注冊(cè)JDBC的驅(qū)動(dòng)類(lèi)
第二步 提供JDBC連接的url 賬號(hào)密碼等信息
第三步 創(chuàng)建數(shù)據(jù)庫(kù)的連接
try {
// 第一步 加載注冊(cè)JDBC的驅(qū)動(dòng)類(lèi)
Class.forName("com.mysql.jdbc.Driver");
// 第二步 提供JDBC連接的url
String url = "jdbc:mysql://localhost:3306/itcast";
String user = "root";
String password = "root";
// 第三步 創(chuàng)建數(shù)據(jù)庫(kù)的連接
Connection conn = DriverManager.getConnection(url, user, password);
} catch (Exception e) {
e.printStackTrace();
}
然后我們用連接Connection對(duì)象的createStatement()函數(shù)方法創(chuàng)建一個(gè)Statement(語(yǔ)句):
語(yǔ)句 相當(dāng)于數(shù)據(jù) InputStream (套接字Socket里面已經(jīng)封住好流)
createStatement()函數(shù)方法說(shuō)明:
Creates a Statement object for sending SQL statements to the database. SQL statements without parameters are normally executed using Statement objects. If the same SQL statement is executed many times, it may be more efficient to use a PreparedStatement object.
創(chuàng)建一個(gè)Statement對(duì)象用來(lái)發(fā)送SQL語(yǔ)句給數(shù)據(jù)庫(kù) SQL語(yǔ)句沒(méi)有參數(shù)昂羡,使用Statement對(duì)象來(lái)執(zhí)行
創(chuàng)建Statement對(duì)象:
注意:我們使用java.sql包下的 不使用com.mysql.jdbc下的Statement來(lái)創(chuàng)建(即選擇截圖中上面的而不是下面的Statement)這樣做是為了解耦合! 這樣代碼換成其他數(shù)據(jù)庫(kù)也同樣適用 面向?qū)ο缶幊桃?高內(nèi)聚 低耦合
創(chuàng)建好語(yǔ)句對(duì)象 我們來(lái)看執(zhí)行的操作:
String sql = "insert into test(id,name,age) values(2, 'ta', 99)";
st.execute(sql);
語(yǔ)句對(duì)象 execute() 方法:
Executes the given SQL statement, which may return multiple results. In some (uncommon) situations, a single SQL statement may return multiple result sets and/or update counts. Normally you can ignore this unless you are (1) executing a stored procedure that you know may return multiple results or (2) you are dynamically executing an unknown SQL string.
執(zhí)行這個(gè)sql語(yǔ)句摔踱,可返回多個(gè)記錄虐先。
單個(gè)sql語(yǔ)句可以返回多個(gè)結(jié)果集或者更新的數(shù)量。除非你對(duì)它執(zhí)行存儲(chǔ)過(guò)程派敷,通常你可以忽視它蛹批。
Returns:
true if the first result is a ResultSet object; false if it is an update count or there are no results
如果第一個(gè)結(jié)果是ResultSet對(duì)象 返回true
否則返false
不是我們理解的返回成功和失敗 即執(zhí)行sql語(yǔ)句返回的是一個(gè)標(biāo)記
返回的說(shuō)明較難理解 通常我們讓其直接執(zhí)行即可 而不用其返回值
在此給出利用其返回值的一個(gè)示例:
// 第五步 執(zhí)行sql語(yǔ)句
String sql = "select * from student";
ResultSet rs = stmt.executeQuery(sql);
// 第六步 循環(huán)遍歷處理結(jié)果
while(rs.next()) {
System.out.println(rs.getString("name"));
System.out.println(rs.getFloat("grade"));
}
執(zhí)行完后要關(guān)閉JDBC對(duì)象 釋放資源:
//關(guān)閉JDBC對(duì)象
rs.close();
stmt.close();
conn.close();
插入數(shù)據(jù)完整代碼:
public class JDBCDemo {
public static void main(String[] args) {
Connection conn = null;
Statement stmt = null;
try {
// 第一步 加載注冊(cè)JDBC的驅(qū)動(dòng)類(lèi)
Class.forName("com.mysql.jdbc.Driver");
// 第二步 提供JDBC連接的url
String url = "jdbc:mysql://localhost:3306/itcast";
String user = "root";
String password = "root";
// 第三步 創(chuàng)建數(shù)據(jù)庫(kù)的連接
conn = DriverManager.getConnection(url, user, password);
// 第四步 創(chuàng)建一個(gè)statement對(duì)象
stmt= conn.createStatement();
// 第五步 執(zhí)行sql語(yǔ)句
String sql = "insert into test(id,name,age) values(2, 'ta', 99)";
stmt.execute(sql);
}catch(ClassNotFoundException e) {
e.printStackTrace();
}catch(SQLException e) {
e.printStackTrace();
}finally{
try {
// 第六步 關(guān)閉JDBC對(duì)象
if(stmt != null) {
stmt.close();
}
if(conn != null) {
conn.close();
}
}catch(SQLException e) {
e.printStackTrace();
}
}
}
}
運(yùn)行代碼:
刷新表后顯示成功插入數(shù)據(jù):
較之前的代碼 只是sql語(yǔ)句不同!
更新數(shù)據(jù)示例:
public class JDBCDemo {
public static void main(String[] args) {
Connection conn = null;
Statement stmt = null;
try {
// 第一步 加載注冊(cè)JDBC的驅(qū)動(dòng)類(lèi)
Class.forName("com.mysql.jdbc.Driver");
// 第二步 提供JDBC連接的url
String url = "jdbc:mysql://localhost:3306/itcast";
String user = "root";
String password = "root";
// 第三步 創(chuàng)建數(shù)據(jù)庫(kù)的連接
conn = DriverManager.getConnection(url, user, password);
// 第四步 創(chuàng)建一個(gè)statement對(duì)象
stmt= conn.createStatement();
// 第五步 執(zhí)行sql語(yǔ)句
String sql = "update test set name='up',age=18 where id=1";
stmt.execute(sql);
}catch(ClassNotFoundException e) {
e.printStackTrace();
}catch(SQLException e) {
e.printStackTrace();
}finally{
try {
// 第六步 關(guān)閉JDBC對(duì)象
if(stmt != null) {
stmt.close();
}
if(conn != null) {
conn.close();
}
}catch(SQLException e) {
e.printStackTrace();
}
}
}
}
id為1的數(shù)據(jù)更新:
刪除數(shù)據(jù)示例:
public class JDBCDemo {
public static void main(String[] args) {
Connection conn = null;
Statement stmt = null;
try {
// 第一步 加載注冊(cè)JDBC的驅(qū)動(dòng)類(lèi)
Class.forName("com.mysql.jdbc.Driver");
// 第二步 提供JDBC連接的url
String url = "jdbc:mysql://localhost:3306/itcast";
String user = "root";
String password = "root";
// 第三步 創(chuàng)建數(shù)據(jù)庫(kù)的連接
conn = DriverManager.getConnection(url, user, password);
// 第四步 創(chuàng)建一個(gè)statement對(duì)象
stmt= conn.createStatement();
// 第五步 執(zhí)行sql語(yǔ)句
String sql = "delete from test where id=2";
stmt.execute(sql);
}catch(ClassNotFoundException e) {
e.printStackTrace();
}catch(SQLException e) {
e.printStackTrace();
}finally{
try {
// 第六步 關(guān)閉JDBC對(duì)象
if(stmt != null) {
stmt.close();
}
if(conn != null) {
conn.close();
}
}catch(SQLException e) {
e.printStackTrace();
}
}
}
}
較之前的代碼 只是sql語(yǔ)句不同篮愉!
id=2的數(shù)據(jù)被刪除:
總結(jié)以上增刪改 操作步驟:
第一步 加載注冊(cè)JDBC的驅(qū)動(dòng)類(lèi)
第二步 提供JDBC連接的url 數(shù)據(jù)庫(kù)賬號(hào)腐芍、密碼
第三步 創(chuàng)建數(shù)據(jù)庫(kù)的連接
第四步 創(chuàng)建一個(gè)statement對(duì)象
第五步 執(zhí)行sql語(yǔ)句
第六步 關(guān)閉JDBC對(duì)象
增刪改 代碼模板:
Connection conn = null;
Statement stmt = null;
try {
// 第一步 加載注冊(cè)JDBC的驅(qū)動(dòng)類(lèi)
Class.forName("com.mysql.jdbc.Driver");
// 第二步 提供JDBC連接的url
String url = "jdbc:mysql://localhost:3306/itcast";
String user = "root";
String password = "root";
// 第三步 創(chuàng)建數(shù)據(jù)庫(kù)的連接
conn = DriverManager.getConnection(url, user, password);
// 第四步 創(chuàng)建一個(gè)statement對(duì)象
stmt= conn.createStatement();
// 第五步 執(zhí)行sql語(yǔ)句
String sql = ...;
stmt.execute(sql);
}catch(ClassNotFoundException e) {
e.printStackTrace();
}catch(SQLException e) {
e.printStackTrace();
}finally{
try {
// 第六步 關(guān)閉JDBC對(duì)象
if(stmt != null) {
stmt.close();
}
if(conn != null) {
conn.close();
}
}catch(SQLException e) {
e.printStackTrace();
}
}
應(yīng)用時(shí)需要對(duì)sql賦予相對(duì)應(yīng)的增刪改的sql指令
String sql = ...;
只查詢(xún)是比較麻煩:
用到Statement對(duì)象的executeQuery()函數(shù)方法:
executeQuery()函數(shù)說(shuō)明:
Executes the given SQL statement, which returns a single ResultSet object.
Parameters:sql an SQL statement to be sent to the database, typically a static SQL SELECT statement
Returns:a ResultSet object that contains the data produced by the given query; never null
返回一個(gè)包含數(shù)據(jù)的ResultSet! 注意 never null 试躏!
因?yàn)槠鋘ever null 所有查詢(xún)數(shù)據(jù)庫(kù)時(shí)不能用以下代碼判斷非空:
rs != null;
(rs 為ResultSet 對(duì)象)
而應(yīng)該用下面的語(yǔ)句判斷非空:
while( rs.next() ) {
...
}
關(guān)于ResultSet的描述:
A table of data representing a database result set, which is usually generated by executing a statement that queries the database.
A ResultSet object maintains a cursor pointing to its current row of data. Initially the cursor is positioned before the first row.
注意:初始游標(biāo)cursor指向第一行之前猪勇。
給出遍歷查詢(xún)數(shù)據(jù)庫(kù)代碼:
public class JDBCDemo {
public static void main(String[] args) {
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
// 第一步 加載注冊(cè)JDBC的驅(qū)動(dòng)類(lèi)
Class.forName("com.mysql.jdbc.Driver");
// 第二步 提供JDBC連接的url
String url = "jdbc:mysql://localhost:3306/itcast";
String user = "root";
String password = "root";
// 第三步 創(chuàng)建數(shù)據(jù)庫(kù)的連接
conn = DriverManager.getConnection(url, user, password);
// 第四步 創(chuàng)建一個(gè)statement對(duì)象
stmt= conn.createStatement();
// 第五步 執(zhí)行sql語(yǔ)句
String sql = "select * from test";
rs = stmt.executeQuery(sql);
// 第六步 遍歷結(jié)果集
while(rs.next()){
int id = rs.getInt("id");
String name = rs.getString("name");
int age = rs.getInt("age");
System.out.println(id + " : " + name + " : " + age);
}
}catch(ClassNotFoundException e) {
e.printStackTrace();
}catch(SQLException e) {
e.printStackTrace();
}finally{
try {
// 第七步 關(guān)閉JDBC對(duì)象
if(rs != null) {
rs.close();
}
if(stmt != null) {
stmt.close();
}
if(conn != null) {
conn.close();
}
}catch(SQLException e) {
e.printStackTrace();
}
}
}
}
運(yùn)行后遍歷打印:
總結(jié)查詢(xún)數(shù)據(jù)7步驟:
第一步 加載注冊(cè)JDBC的驅(qū)動(dòng)類(lèi)
第二步 提供JDBC連接的url 數(shù)據(jù)庫(kù)賬號(hào)颠蕴、密碼
第三步 創(chuàng)建數(shù)據(jù)庫(kù)的連接
第四步 創(chuàng)建一個(gè)statement對(duì)象
第五步 執(zhí)行sql語(yǔ)句
第六步 遍歷結(jié)果集
第七步 關(guān)閉JDBC對(duì)象