Java----JDBC資料庫開發
JDBC是實作Java同各種資料庫連接配接的關鍵,它提供了将Java和資料庫連接配接起來的程式接口,使使用者可以以SQL的形式編寫通路請求,然後傳給資料庫,其結果再由這一接口傳回。JDBC又是一個使Java得到擴充的主角,它是程式員能夠輕松地使用Java語言連接配接資料庫。
1、通過JDBC通路資料庫
JDBC是Java DataBase Connectivity的縮寫,它提供了執行SQL語句、通路關系資料庫的方法。JDBC是有Java程式設計語言編寫的類及接口組成,同時它也為程式開發人員提供了一組用于實作對資料庫通路的JDBCAPI,并支援SQL語言。利用JDBC可以将Java代碼連接配接到Oracle、DB2、SQLServer、MySQL等資料庫,進而實作對資料庫中的資料進行操作的目的。
JDBC類似于Microsoft的ODBC,但JDBC是Java操作資料庫的方法,而ODBC是使用C語言接口。通過使用JDBC,程式員可以很友善地将SQL語句傳給任何一種資料庫。也就是說程式員不需要寫多個程式分别對應不同的資料庫。用JDBC編寫的程式能自動将SQL語句傳給相應的資料庫管理系統(DBMS)。
對于資料庫這裡就不做詳細的說明了,這裡隻說一下資料庫語言及其操作吧。SQL是Structured Query Language的縮寫,它是一種介于關系代數與關系鹽酸之間的機構化查詢語言,是許多關系資料庫定義及查詢資料的語言。Java是一門過程化語言,而SQL是一門高度非過程化語言。SQL的精華在于不管多麼複雜的操作,它隻有一句。它隻要告訴系統做什麼,系統就會照做,而不是告訴系統怎麼做。資料庫的操作概括成4個字就是贈、删、改、查。
1)、建立表
SQL語言使用CREATE TABLE語句來定義基本表,其一般格式為:
CREATE TABLE 表名(
字段1 字段類型 限制條件,
字段2 字段類型 限制條件,......
);
看一個學生表的建立,在表中定義了學号、姓名、年齡和性别幾項列明:
CREATE TABLE student(
ID varchar(10)not null,
Name varchar(10),
Age varchar(3),
Sex varchar(1)
);
系統執行CREATE語句後,就會在資料庫中建立一個新表。關于資料類型,每種資料庫的資料類型是有一些不一樣的,用到哪種資料庫以後隻要看一眼就知道了。
2)、插入資料
表建立好後,即可插入資料。插入資料的基本格式為:
INSERT INTO 表名(字段1,字段2......)
VALUES(值1,值2....);
如果向每個字段名下都插入資料,其中的字段名就不用寫的,将變為:
INSERT INTO 表名
VALUES(值1,值2......);
應用前面建立的學生表,舉一個插入資料的例子:
INSERT INTO student(ID ,Name , Sex)
VALUES(‘41009160’ , ‘小武靈靈’ , ‘男’);
上面是一個不知道年齡的學生的資訊,再來看一個完整的學生的資訊:
INSERT INTO student
VALUES(‘41009161’ , ‘小龍’ , ‘23’,‘男’);
在插入資料時,經常會遇到資料插入不進去的問題,這時一定要檢查資料是否違反了建立表時規定的限制條件。如在建立表時規定學号不能為空,而在插入資料時沒有插入學号,這時就會報錯。
3)、檢視資料
插入資料後,經常要看資料是否真的加入資料庫,這時就要用到檢視資料指令。查詢語句為:
SELECT[ALL|DEITINCT] 字段名[字段名清單達式]
FROM 表名
[WHERE 條件表達式]
[GROUP BY 字段名1[HAVING 條件表達式]]
[ORDER BY 字段名2[ASC|DESC]]
檢視資料的意思就是根據給出的限制條件在資料庫中提取需要的資料。其中[GROUP BY 字段名1[HAVING 條件表達式]]指的是對字段1按條件表達式對資料分組。 [ORDER BY 字段名2 [ASC|DESC]]指的是對字段名3進行升序或降序排序。
如果查詢所有資料,還有一個簡單的格式:
SELECT * FROM 表名;
如對以前建立的表查詢所有資料:
SELECT * FROM student;
有時隻關心學号和姓名,即可使用指定字段名的查詢語句,如:
SELECT ID , Name FROM student;
還有人想看誰比他的年齡大(假設他的年齡是20),資料庫也提供了相應查詢方法,這時就要用[WHERE 條件表達式],其查詢語句為:
SELECT Name , Age FROMstudent WHERE Age > 20;
還是有人可能想直接看别人的年齡比他小多少,這時就要用到[字段名清單達式],其查詢語句如下:
SELECT Name , Age-20 FROM studentWHERE Age > 20;
還有一種很特殊的情況,如果查詢年齡為20且學号大于41009100的資料,這時就要用到條件運算符。WHERE子句的全部條件運算符如下表所示:
條件運算符 | 運算符 |
比較運算符 | < , <= , = , != , > , >= , <> |
範圍運算符 | BETWEEN AND , NOT BETWEEN AND |
集合運算符 | IN , NOT IN |
字元比對運算符 | LIKE , NOT LIKE |
空值判斷符 | IS NULL , IS NOT NULL |
邏輯運算符 | AND OR NOT |
應用條件運算符後,其查詢語句為:
SELECT Name , Age , ID FROMstudent WHERE Age = 20 AND ID>41009160;
3、JDBC程式設計步驟
JDBC程式設計的基本步驟是設定資料源、加載JDBC驅動器程式、指定資料庫、打開資料庫連接配接、送出查詢、處理查詢結果等。在講解程式設計步驟錢,先看一段代碼,一邊學習代碼,一遍學習變成步驟。
public class test {
public static void main(String[] args){
try {
//加載驅動程式
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
//打開資料庫連接配接,aaa為資料源名稱
Connection con =DriverManager.getConnection("jdbc:odbc:aaa" , "" ,"");
//送出查詢
Statement st =con.createStatement();
//向資料庫中插入一條記錄
st.executeUpdate("insert intostudent values('41009160' , '小武靈靈' , '22' , '男'");
//取得查詢結果
ResultSet rs =st.executeQuery("select * from student");
//檢視結果
System.out.println("ID/Name/Age/Sex");
while (rs.next()) {
String ID =rs.getString("ID");
String Name =rs.getString("Name");
String Age =rs.getString("Age");
String Sex =rs.getString("Sex");
System.out.println(ID +"/" + Name + "/" + Age + "/" + Sex);
}
rs.close();//關閉RsultSet對象
st.close();//關閉Statement對象
con.close();//關閉Connection對象
} catch (Exception e) {
e.printStackTrace();
}
}
}
上面的程式中進行了資料庫的連接配接,使用了資料源,并将資料庫建立好,最後将它的資料庫名稱輸出。
1)、建立資料源
JDBC程式設計時,必須先建立ODBC資料源。作業系統和使用的資料庫不同可能會有所不同,但是具體步驟是不會變的。
(1)、Windows桌面 → 開始→ 控制台 → 管理工具 → 資料源(ODBC),彈出ODBC資料管理器對話框;
(2)、添加 → 建立新資料源對話框 → 根據使用的資料庫進行選擇,這裡以Access為例 → 選擇Access選項 → 完成;
(3)、彈出“OBDC MicrosoftAccess安裝”對話框,在“資料源名”文本框中根據自己的需要命名,在此輸入aaa;
(4)、單擊“确定“按鈕,可以看到多出一個名為aaa的資料源。
2)、加載驅動程式
可以通過調用方法Class.forName來加載驅動程式。加載驅動程式隻需要一行代碼就能完成,以JDBC-ODBC橋接、Oracle連接配接和MySQL連接配接為例,檢視它們的驅動程式:
>JDBC-ODBC橋接:sun.jdbc.odbc.JdbcOdbcDriver;
>Oracle連接配接:oracle.jdbc.driver.OracleDriver;
>MySQL連接配接:org.gjt.mm.mysql.Driver.
當使用Oracle和MySQL連接配接相應的資料源時,要在classpath中加入相應的配置。
3)、指定資料庫
JDBC URL提供了一種标志特定的驅動程式,它可以使相應的驅動程式能識别該資料庫并與之建立連接配接。由于JDBC URL要與各種不同的驅動程式一起使用,是以對它的約定也是非常少的。第一,它允許不同的驅動程式使用不同的方案來命名資料庫。第二,JDBC URL允許驅動程式程式設計将一切所需的資訊編入其中。這樣就可以讓要與給定資料庫對話的applet打開資料庫連接配接,而不用要求使用者去做任何系統管理工作。第三,JDBC URL應允許某種程式的間接性。也就是說JDBC URL可指向邏輯主機或資料庫名,而這種邏輯主機或資料庫名将由網絡命名系統動态地轉換為實際的名稱。
JDBC URL的标準文法如下所示,它有3部分組成,各部分之間用冒号分隔:
Jdbc:<子協定>:<子名稱>
在JDBC程式設計中,JDBC URL中的協定總是JDBC,JDBC是永遠不變的。<子協定>指的是驅動程式名或資料庫連接配接機制的名稱。<子名稱>是一種辨別資料庫的方法。這裡還是以JDBC-ODBC橋接、Oracle連接配接和MySQL連接配接為例,它們分别是:
>jdbc:odbc:資料源名
>jdbc:oracle:thin:@資料庫伺服器主機名:1521:SID
>jdbc:mysql:://localhost/<資料庫名稱>
4)、打開資料庫連接配接
Connection對象代表與資料庫的連接配接。連接配接過程包括所執行的SQL語句和在該連接配接上所傳回的結果。一個應用程式可與單個資料庫有一個或多個連接配接,或者可與許多資料庫有連接配接。打開資料庫連接配接就是用适當的驅動程式與資料管理系統建立一個連接配接。DriverManager類時JDBC的管理層,作用于使用者和驅動程式之間。它跟蹤可用的驅動程式,并在資料庫和相應驅動程式之間建立連接配接。加載驅動程式并在DriverManager類中注冊後,即可與資料庫建立連接配接。當調用DriverManager.getConnection方法發出連接配接請求時,DriverManager将驗證每個驅動程式,檢視它是否可以建立連接配接。打開使用者名為user,密碼未password的資料庫連接配接的基本代碼為:
Connection con =DriverManager.getConnection(url , “user” , “password”);
這段代碼看起來很簡單,其實包括怎樣提供URL這個難點,是以有時會把這段代碼分為兩段:
String url = “jdbc:odbc:aaa”;
Connection con =DriverManager.getConnection(url , “user” , “password”);
DriverManager類包含一系列Driver類,它們已認證調用方法DriverManager.registerDriver對自己進行了注冊。加載Driver類并在DriverManager類中注冊後,它們即可用來與資料庫建立連接配接。當調用DriverManager.getConnection方法發出連接配接請求時,DriverManager将檢查每個驅動程式,檢視它是否可以建立連接配接。
5)、送出查詢
與資料源建立連接配接後,即可向它所關聯的資料庫發送SQL語句。JDBC對可被發送的SQL語句類型不加任何限制。
Statement對象用于将SQL語句發送到資料庫中。有3中Statement對象,它們都作為在給定連接配接上執行SQL語句的包容器:Statement、PreparedStatement(它從Statement繼承而來)和CallableStatement(它從PreparedStatement繼承而來)。它們都專門用于發送特定類型的SQL語句:Statement對象用于執行不帶參數的簡單SQL語句;PreparedStatement對象用于執行帶或不帶IN參數的預編譯SQL語句;CallebelStatement對象用于執行對資料庫已存儲過程的調用。
送出查詢應用Statement對象的代碼如下。Statement是Connection接口的一個常用對象,由方法creatStatement建立。Statement獨享用于發送SQL語句。送出查詢的代碼為:
Statement stmt = con.createStatement();
6)、取得查詢結果
編寫了SQL對象後,即可應用它調用相應的方法實作對資料庫的查詢和修改。并将查詢結果放在一個ResultSet類聲明的對象中,SQL語句對資料庫的查詢操作将傳回一個ResultSet對象。其代碼為:
ResultSet rs =stmt.excuteQuery(“SELECT * FROM 表名”);
查詢結果作為一個行的集合,也可以說是一個表存在一個ResultSet對象中。ResultSet包含符合SQL語句中條件的所有行,ResultSet.net()方法用于移動到ResultSet中的下一行,使下一行稱為目前行,并傳回一個boolean值表示該行是否為最後一行。ResultSet維護指向其目前資料行的光标。光标最初在第一行之前,是以第一次調用next()将把光标置于第一行上。每調用一次next()方法,光标向下移動一行。當光标移至最後一行時next()方法傳回false。
ResultSet包含符合SQL語句中條件的所有行,并且它通過一套get()方法提供了隊這些行中資料的通路方法。get()提供了擷取目前行中某列值的途徑。在每行中可按從左到右的次序擷取列值。列名或列号可用于辨別要從中擷取資料的列。get()方法很多,如下表所示:
get方法 | 傳回類型 |
getBoolean | Boolean |
getByte | Byte |
getByes | Byte[] |
getDate | Java.sql.Date |
getDouble | Double |
getFloat | Float |
getInt | Int |
getLong | Long |
getObject | Object |
getShort | Short |
getString | Java.lang.String |
getTime | Java.sql.Time |
getTimestamp | Java.sql.Timestamp |
4、使用PreparedStatement進行預編譯操作
當一個Statement對象被建立時,它提供了建立SQL查詢、執行該查詢和檢索傳回結果的作用。PreparedStatement接口繼承自Statement,與Statement相比,PreparedStatement增加了在執行SQL調用之前将輸入參數綁定到SQL調用中的能共。它用于執行帶或不帶輸入參數的預編譯SQL語句。因為PreparedStatement對象已編譯過,是以執行速度要快于Statement對喜愛那個。是以當需要多次調用一條SQL語句時,可以考慮使用PreparedStatement接口。
PreparedStatement接口繼承了Statement 所有方法,同時增加了一些方法,還更改了3個很重要的方法,它們是:
>setXXX();
>executeQuery();
>executeUpdate();
其中,setXXX()方法中的XXX指的是該參數對應了類型。例如參數是String類型,則方法為SetString()。SetXXX()方法有兩個參數,第一個參數是指要設定參數的位置,第二個參數是指要設定的具體指。例如ps.setInt(1 , 2000);
如果基本資料庫和驅動程式在語句送出之後扔保持這些語句的打開狀态,則同一個PreparedStatement可執行多次。如果這一點不成立,那麼試圖通過使用PreparedStatement對象代替Statement對象來提高性能是沒有意義的。
下面是使用PreparedStatement的一段代碼:
public class test {
public static void main(String[] args){
try {
//加載驅動程式
Class.forName("jdbc.odbc.JdbcOdbcDriver");
//打開資料庫連接配接,aaa為資料源名稱
Connection con =DriverManager.getConnection("jdbc:odbc:aaa", "","");
//送出查詢
PreparedStatement ps =con.prepareStatement("select * from student where Age>?");
ps.setString(1, "23");
ResultSet rs = ps.executeQuery();
//檢視結果
System.out.println("ID/Name/Age/Sex");
while (rs.next()) {
String ID = rs.getString(1);
String Name = rs.getString(2);
String Age = rs.getString(3);
String Sex = rs.getString(4);
System.out.println(ID +"/" + Name + "/" + Age + "/" + Sex);
}
rs.close();
ps.close();
con.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
5、中繼資料
中繼資料用于描述資料庫或一部分資料庫的資料,它是關于資料的資料。中繼資料被用于動态地調節資料庫的内容和結果集。它分為兩類:關于資料庫的和關于結果集的。
1)、資料庫的DatabaseMetaData中繼資料
DatabaseMetaData對象能夠提供關于特定資料庫的結果的資訊。DatabaseMetaData對象通過資料庫的連接配接獲得,方法如下:
DatabaseMetaData dmd = con.getMetaData();
DatabaseMetaData對象提供的方法很多,這些方法可以通過對傳回結果的類型分為4類,它們分别是傳回字元串、整數、布爾值和ResultSet的方法。例如下面的方法傳回一個ResultSet:
getTables(String catalog ,String checmaPattern , String tableNamePattern , String types[]);
2)結果集的ResultSetMetaData中繼資料
ResultSetMetaData是關于結果集的中繼資料。它可以通過getMetaData()方法從ResultSet獲得中繼資料:
ResultSetMetaData esmd =rs.getMetaData();
ResultSetMetaData的方法也很多,通過getColumnCount()方法來進行舉例說明,它被用于傳回ResultSet對象中的列數:
public class test {
public static void main(String[] args){
try {
Class.forName("jdbc.odbc.JdbcOdbcDriver");
Connection con =DriverManager.getConnection("jdbc:odbc:aaa" , "" ,"");
//定義DatabaseMetaData對象
DatabaseMetaData dmd =con.getMetaData();
//檢索可在給定類别中使用的表的描述
ResultSet rs = dmd.getTables(null,null, null, new String[]{"table"});
//定義ResultSetMetaData對象
ResultSetMetaData rsmd =rs.getMetaData();
//傳回次ResultSet對象中的列數
int cols = rsmd.getColumnCount();
for (int i = 0; i < cols; i++) {
//擷取指定咧的名稱
System.out.print(rsmd.getColumnName(i) + "\t");
}
System.out.println("");
while (rs.next()) {
for (int i = 0; i < cols;i++) {
System.out.println(rs.getString(i) + "\t");
}
System.out.println("");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
6、結果集處理
在前面的執行個體中,都是假設結果集是隻讀的。對結果集的處理可分為可滾動的和可更新的。可滾動是指顯示的結果集的遊标所在行既可以向前移又可以向後移動,也可以移動到指定的特定行。可更新是指允許客戶程式對結果集中的資料進行修改。
1)、可滾動結果集
JDBC驅動程式是否支援可滾動的結果集是由DatabaseMetaData對象決定的。DatabaseMetaData接口中定義了一個supportsResultSetType(inttype)方法,它的傳回結果為boolean型,其作用是用于檢查此資料庫是否支援給定的結果集類型。在實際的程式開發中,并不用DatabaseMetaData進行開發,而是用Statement直接指定,如下面的程式代碼:
Statement st =con.createStatement(type , concurrency);
其中type有3種類型
>TYPE_FORWARD_ONLY:結果集遊标隻能向前移動
>TYPE_SCROLL_INSENSITIVE:可滾動,對資料變化不敏感
>TYPE_SCROLL_SENSITIVE:可滾動,對資料變化敏感
對結果集進行操作就是對結果集的遊标進行操作,其中定義了很多種方法:
>absolute(int row):把遊标移至給定的行
>afterLast():把遊标移至最後一行後面
>beforeFirst():把遊标移至第一行前面
>isAfterLast():判斷遊标是否在最後一行後面
>isBeforeFirst():判斷遊标是否在第一行前面
>first():把遊标移動到第一行
>last():把遊标移動到最後一行
>isFirst():判斷遊标是否在第一行
>isLast():判斷遊标是否在最後一行
>previous():把遊标移動到所在行的前一行
>next():把遊标移動到所在行的後一行
>relative(intt):把遊标相對移動幾行
>getRow():擷取目前行數
下面是對某些方法的使用:
public class test {
public static void main(String[] args){
try {
Class.forName("jdbc.odbc.JdbcOdbcDriver");
Connection con =DriverManager.getConnection("jdbc:odbc:aaa", "","");
Statement st =con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);
ResultSet rs =st.executeQuery("select * from student");
//檢視結果
rs.absolute(2);
System.out.println(rs.getString(1));
rs.previous();
System.out.println(rs.getString(1));
rs.first();
System.out.println(rs.getString(1));
rs.relative(3);
System.out.println(rs.getString(1));
System.out.println(rs.getRow() +"");
rs.close();
st.close();
con.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
2)、可更新結果集
在ResultSet類中是用getConcurrency方法來确定結果集是否為可更新的。ResultSet接口中有很多的更新方法,列舉如下:
>updateBoolean():用布爾類型的值更新指定的列
>updateByte():用位元組值更新指定的列
>updateBytes():用位元組數組值更新指定的列
>updateCharacterStream():用字元流的值更新指定的列
>updateDate():用date值更新指定的列
>updateDouble():用double類型的值更新指定的列
>updateFloat():用float類型的值更新指定的列
>updateInt():用int類型的值更新指定的列
>updateLong():用long類型的值更新指定的列
>updateNull():給可為null的列指定null值
>updateObject():用object值更新指定的列
>updateRow():用resultset對象的新内容更新
>updateShort():用short類型的值更新指定的列
>updateString():用字元串類型的值更新指定的列
>updateTime():用time值更新指定的列
可更新結果集的程式和可滾動的結果集程式很相似,但是可更新的結果集圓沒有可滾動結果集重要,這裡不再給出可更新結果集的代碼。