本人的環(huán)境為Myeclipse10允坚、MySQL5.7.15
本文包括:
- 簡(jiǎn)介
- JDBC編程步驟
- 打通數(shù)據(jù)庫(kù)
- 程序詳解—DriverManager
- 程序詳解—Connection
- 程序詳解—Statement
- 程序詳解—ResultSet
- 進(jìn)階應(yīng)用—ResultSet滾動(dòng)結(jié)果集
- 程序詳解—釋放資源
- 編寫工具類簡(jiǎn)化CRUD操作
- PreparedStatement-防止SQL注入
- 使用JDBC進(jìn)行批處理
- JavaEE體系結(jié)構(gòu)
1祖凫、 簡(jiǎn)介
Java Data Base Connectivity(Java數(shù)據(jù)庫(kù)連接):是java與數(shù)據(jù)庫(kù)的橋梁,提供讀寫操作方面。
可以為多種數(shù)據(jù)庫(kù)提供統(tǒng)一的訪問(wèn),是一種統(tǒng)一標(biāo)準(zhǔn)结窘。
通過(guò)JDBC可以連接Oracle怖喻、MySql底哗、Sql Server數(shù)據(jù)庫(kù)。
2罢防、JDBC編程步驟
簡(jiǎn)單來(lái)說(shuō):
加載驅(qū)動(dòng)程序
建立連接
操作數(shù)據(jù)
釋放資源
具體而言:
通過(guò)DriverManager加載驅(qū)動(dòng)程序driver艘虎;
通過(guò)DriverManager類獲得表示數(shù)據(jù)庫(kù)連接的Connection類對(duì)象;
通過(guò)Connection對(duì)象綁定要執(zhí)行的語(yǔ)句咒吐,生成Statement類對(duì)象;
執(zhí)行SQL語(yǔ)句属划,接收?qǐng)?zhí)行結(jié)果集ResultSet恬叹;
可選的對(duì)結(jié)果集ResultSet類對(duì)象的處理;
必要的關(guān)閉ResultSet同眯、Statement和Connection
3绽昼、打通數(shù)據(jù)庫(kù)
-
需要導(dǎo)入mysql-connector-java的jar包,如圖所示:
注意:可以直接將數(shù)據(jù)庫(kù)驅(qū)動(dòng)的jar包復(fù)制到/WebRoot/WEB/INF/lib/目錄下须蜗,這時(shí)候根目錄的Referenced Libraries 中會(huì)直接出現(xiàn)這個(gè)jar包硅确。如果像圖示的這樣操作目溉,那么還需要在這個(gè)jar包上單擊右鍵-build path,把它添加到path中菱农。
-
加載驅(qū)動(dòng)程序:
Class.forName(driverClass)
-
加載Mysql驅(qū)動(dòng):
Class.forName("com.mysql.jdbc.Driver")
-
加載Oracle驅(qū)動(dòng):
Class.forName("oracle.jdbc.driver.OracleDriver")
為什么要用反射技術(shù)來(lái)加載驅(qū)動(dòng)程序呢缭付?詳情見(jiàn)下文DriverManager的介紹。
-
-
獲得數(shù)據(jù)庫(kù)連接:
-
getConnection方法:
DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/imooc", USER, PASSWORD);
其中jdbc:mysql表示jdbc連接mysql循未,127.0.0.1:3306為服務(wù)器地址和端口陷猫,imooc為數(shù)據(jù)庫(kù)名稱,USER和PASSWORD分別為數(shù)據(jù)庫(kù)的用戶名和密碼的妖。
-
URL:
jdbc:mysql://localhost:3306/test?key=value&key=value
-
省略寫法:
jdbc:mysql:///test
-
URL中常用的參數(shù):
useUnicode=true&characterEncoding=UTF-8(注意:這里的字符集應(yīng)該與客戶端保持一致)
-
-
-
通過(guò)數(shù)據(jù)庫(kù)的連接操作數(shù)據(jù)庫(kù)绣檬,創(chuàng)建Statement對(duì)象:
Statement stmt = conn.createStatement();
4、程序詳解—DriverManager
-
Jdbc程序中的DriverManager用于加載驅(qū)動(dòng)嫂粟,并創(chuàng)建與數(shù)據(jù)庫(kù)的鏈接娇未,這個(gè)API的常用方法:
DriverManager.registerDriver(new Driver()); DriverManager.getConnection(url, user, password)星虹;
注意:在實(shí)際開(kāi)發(fā)中并不推薦采用registerDriver方法注冊(cè)驅(qū)動(dòng)零抬。
原因有二:
查看Driver的源代碼可以看到,如果采用此種方式搁凸,會(huì)導(dǎo)致驅(qū)動(dòng)程序注冊(cè)兩次媚值,也就是在內(nèi)存中會(huì)有兩個(gè)Driver對(duì)象。
程序依賴mysql的api护糖,脫離mysql的jar包褥芒,程序?qū)o(wú)法編譯,將來(lái)程序切換底層數(shù)據(jù)庫(kù)將會(huì)非常麻煩嫡良。
-
推薦方式:
Class.forName(“com.mysql.jdbc.Driver”);
采用此種方式不會(huì)導(dǎo)致驅(qū)動(dòng)對(duì)象在內(nèi)存中重復(fù)出現(xiàn)锰扶,并且采用此種方式,程序僅僅只需要一個(gè)字符串寝受,不需要依賴具體的驅(qū)動(dòng)坷牛,即不需要import相關(guān)的包,使程序的靈活性更高很澄。
同樣京闰,在開(kāi)發(fā)中也不建議采用具體的驅(qū)動(dòng)類型指向getConnection方法返回的connection對(duì)象。
5甩苛、程序詳解—Connection
-
Jdbc程序中的Connection蹂楣,它用于代表數(shù)據(jù)庫(kù)的鏈接,Collection是數(shù)據(jù)庫(kù)編程中最重要的一個(gè)對(duì)象讯蒲,客戶端與數(shù)據(jù)庫(kù)所有交互都是通過(guò)connection對(duì)象完成的痊土,這個(gè)對(duì)象的常用方法有兩種:
-
獲得操作數(shù)據(jù)庫(kù)Statement對(duì)象
- createStatement():創(chuàng)建向數(shù)據(jù)庫(kù)發(fā)送sql的statement對(duì)象
prepareStatement(String sql) :創(chuàng)建向數(shù)據(jù)庫(kù)發(fā)送預(yù)編譯sql的PrepareSatement對(duì)象,它是statement的子接口墨林。
prepareCall(sql):創(chuàng)建執(zhí)行存儲(chǔ)過(guò)程的callableStatement對(duì)象赁酝,它是PrepareStatement的子接口犯祠。 --- 存儲(chǔ)過(guò)程
-
進(jìn)行事務(wù)控制
- setAutoCommit(boolean autoCommit):設(shè)置事務(wù)是否自動(dòng)提交。
commit() :在鏈接上提交事務(wù)酌呆。 ---與事務(wù)相關(guān):庠亍!
rollback() :在此鏈接上回滾事務(wù)肪笋。
-
-
示例:
Statement stmt = conn.createStatement();
6月劈、程序詳解—Statement
-
Jdbc程序中的Statement對(duì)象用于向數(shù)據(jù)庫(kù)發(fā)送SQL語(yǔ)句, Statement對(duì)象常用方法:
executeQuery(String sql) :用于向數(shù)據(jù)發(fā)送查詢語(yǔ)句藤乙。select語(yǔ)句猜揪,返回值ResultSet結(jié)果集。
executeUpdate(String sql):用于向數(shù)據(jù)庫(kù)發(fā)送insert坛梁、update或delete語(yǔ)句而姐。返回值為int:受影響行數(shù)。
-
execute(String sql):用于向數(shù)據(jù)庫(kù)發(fā)送任意sql語(yǔ)句划咐,返回值為boolean:如果第一個(gè)結(jié)果為 ResultSet 對(duì)象拴念,則返回 true;如果其為更新計(jì)數(shù)或者不存在任何結(jié)果褐缠,則返回 false 政鼠。
批處理:
addBatch(String sql) :把多條sql語(yǔ)句放到一個(gè)批處理中。
executeBatch():向數(shù)據(jù)庫(kù)發(fā)送一批sql語(yǔ)句執(zhí)行队魏。
-
示例:
//executeQuery(String sql) 用法 ResultSet rs = stmt.executeQuery("select * from users"); //execute(String sql)用法 stmt.execute("update a set name ='bbb' where id = 1"); //executeUpdate(String sql)用法 int row = stmt.executeUpdate(sql);
7公般、程序詳解—ResultSet
Jdbc程序中的ResultSet用于代表Sql語(yǔ)句的執(zhí)行結(jié)果。Resultset封裝執(zhí)行結(jié)果時(shí)胡桨,采用的類似于表格的方式官帘。ResultSet 對(duì)象維護(hù)了一個(gè)指向表格數(shù)據(jù)行的游標(biāo)cursor,初始的時(shí)候昧谊,游標(biāo)在第一行之前刽虹,調(diào)用ResultSet.next() 方法,可以使游標(biāo)指向具體的數(shù)據(jù)行呢诬,進(jìn)而調(diào)用方法獲取該行的數(shù)據(jù)涌哲。
-
ResultSet既然用于封裝執(zhí)行結(jié)果的,所以該對(duì)象提供的大部分方法都是用于獲取數(shù)據(jù)的get方法:
-
獲取任意類型的數(shù)據(jù)
getObject(int index)
getObject(string columnName)
-
獲取指定類型的數(shù)據(jù)尚镰,例如:
getString(int index)
getString(String columnName)
getInt(int index)
getInt(String columnNmae)
...
-
常用數(shù)據(jù)類型轉(zhuǎn)換表
-
遍歷查詢結(jié)果
-
-
示例:
ResultSet rs = stmt.executeQuery("select * from users"); while (rs.next()) { System.out.println(rs.getInt("id")); System.out.println(rs.getString("name")); System.out.println(rs.getString("pwd")); System.out.println(rs.getString("email")); // 通過(guò)rs進(jìn)行取值時(shí)膛虫,可以使用列名 或 索引 ---- 經(jīng)常用列名,因?yàn)榭勺x性更強(qiáng) System.out.println(rs.getInt(1)); System.out.println(rs.getString(2)); System.out.println(rs.getString(3)); System.out.println(rs.getString(4)); System.out.println("-----------------------------"); }
-
思考:如果明知道某條SQL語(yǔ)句只返回一行數(shù)據(jù)钓猬,還用while?
if(rs.next){ // 因?yàn)榻Y(jié)果只有1行撩独,存在敞曹,不存在 }
8账月、進(jìn)階應(yīng)用—ResultSet滾動(dòng)結(jié)果集
-
ResultSet還提供了對(duì)結(jié)果集進(jìn)行滾動(dòng)和更新的方法。
若想設(shè)置可滾動(dòng)的結(jié)果集澳迫,則在創(chuàng)建Statement對(duì)象時(shí)局齿,不能像前文那樣調(diào)用無(wú)參方法,而應(yīng)該如下設(shè)置:Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);
next():移動(dòng)到下一行
previous():移動(dòng)到前一行
absolute(int row):移動(dòng)到指定行
beforeFirst():移動(dòng)resultSet的最前面
afterLast() :移動(dòng)到resultSet的最后面
updateString(int columnIndex, String x) :用 String 值更新指定列橄登。
updateString(String columnLabel, String x) :用 String 值更新指定列抓歼。
...
updateRow() :更新行數(shù)據(jù),最后要調(diào)用這個(gè)方法來(lái)確認(rèn)
-
示例:
public void demo5() throws Exception { // 設(shè)置可滾動(dòng)結(jié)果集 Class.forName("com.mysql.jdbc.Driver"); Connection conn = DriverManager.getConnection("jdbc:mysql:///day13", "root", "123"); // 參數(shù):TYPE_SCROLL_SENSITIVE 可滾動(dòng) 拢锹、CONCUR_UPDATABLE 可修改 Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = stmt.executeQuery("select * from users"); // 游標(biāo)移動(dòng)到rs的第三行 rs.absolute(3); System.out.println(rs.getString("name")); // 更新第四列的值 rs.updateString(4, "def@itcast.cn"); // 確認(rèn)動(dòng)作 rs.updateRow(); rs.close(); stmt.close(); conn.close(); }
-
可以用以下兩種方式使用更新方法:
-
更新當(dāng)前行中的列值谣妻。在可滾動(dòng)的 ResultSet 對(duì)象中,可以向前和向后移動(dòng)光標(biāo)卒稳,將其置于絕對(duì)位置或相對(duì)于當(dāng)前行的位置蹋半。以下代碼片段更新 ResultSet 對(duì)象 rs 第五行中的 NAME 列,然后使用方法 updateRow 更新導(dǎo)出 rs 的數(shù)據(jù)源表充坑。
rs.absolute(5); // moves the cursor to the fifth row of rs rs.updateString("NAME", "AINSWORTH"); // updates the // NAME column of row 5 to be AINSWORTH rs.updateRow(); // updates the row in the data source
-
將列值插入到插入行中减江。可更新的 ResultSet 對(duì)象具有一個(gè)與其關(guān)聯(lián)的特殊行捻爷,該行用作構(gòu)建要插入的行的暫存區(qū)域 (staging area)辈灼。以下代碼片段將光標(biāo)移動(dòng)到插入行,構(gòu)建一個(gè)三列的行也榄,并使用方法 insertRow 將其插入到 rs 和數(shù)據(jù)源表中巡莹。
rs.moveToInsertRow(); // moves cursor to the insert row rs.updateString(1, "AINSWORTH"); // updates the // first column of the insert row to be AINSWORTH rs.updateInt(2,35); // updates the second column to be 35 rs.updateBoolean(3, true); // updates the third column to true rs.insertRow(); rs.moveToCurrentRow();
-
9、程序詳解—釋放資源
Jdbc程序運(yùn)行完后手蝎,切記要釋放程序在運(yùn)行過(guò)程中榕莺,創(chuàng)建的那些與數(shù)據(jù)庫(kù)進(jìn)行交互的對(duì)象,這些對(duì)象通常是ResultSet, Statement和Connection對(duì)象棵介。
特別是Connection對(duì)象钉鸯,它是非常稀有的資源,用完后必須馬上釋放邮辽,如果Connection不能及時(shí)唠雕、正確的關(guān)閉,極易導(dǎo)致系統(tǒng)宕機(jī)吨述。Connection的使用原則是盡量晚創(chuàng)建岩睁,盡量早的釋放。
為確保資源釋放代碼能運(yùn)行揣云,資源釋放代碼也一定要放在finally語(yǔ)句中捕儒。
-
釋放資源的標(biāo)準(zhǔn)寫法:
public void demo6() throws ClassNotFoundException { // 釋放資源 標(biāo)準(zhǔn)寫法 Class.forName("com.mysql.jdbc.Driver"); Connection conn = null; Statement stmt = null; ResultSet rs = null; try { conn = DriverManager.getConnection("jdbc:mysql:///day13", "root", "123"); stmt = conn.createStatement(); rs = stmt.executeQuery("select * from users"); while (rs.next()) { System.out.println(rs.getString("name")); } } catch (SQLException e) { e.printStackTrace(); } finally { //標(biāo)準(zhǔn)寫法:先關(guān)rs、再stmt、最后conn if (rs != null) { try { rs.close(); } catch (SQLException sqlEx) { } rs = null; } if (stmt != null) { try { stmt.close(); } catch (SQLException sqlEx) { } stmt = null; } if (conn != null) { try { conn.close(); } catch (SQLException e) { } conn = null; } } }
10刘莹、編寫工具類簡(jiǎn)化CRUD操作
dbconfig.properties文件:
DRIVERCLASS=com.mysql.jdbc.Driver
URL=jdbc:mysql:///day14
USER=root
PWD=123
#DRIVERCLASS=oracle.jdbc.driver.OracleDriver
#URL=jdbc:oracle:thin:@localhost:1521:xe
#USER=system
#PWD=123
JDBCUtils文件:
package cn.itcast.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ResourceBundle;
/**
* JDBC 工具類阎毅,抽取公共方法
*
* @author seawind
*
*/
public class JDBCUtils {
private static final String DRIVERCLASS;
private static final String URL;
private static final String USER;
private static final String PWD;
//從dbconfig.properties文件中得到四個(gè)參數(shù),方便切換數(shù)據(jù)庫(kù)
static {
ResourceBundle bundle = ResourceBundle.getBundle("dbconfig");
DRIVERCLASS = bundle.getString("DRIVERCLASS");
URL = bundle.getString("URL");
USER = bundle.getString("USER");
PWD = bundle.getString("PWD");
}
// 建立連接
public static Connection getConnection() throws Exception {
loadDriver();
return DriverManager.getConnection(URL, USER, PWD);
}
// 裝載驅(qū)動(dòng)
private static void loadDriver() throws ClassNotFoundException {
Class.forName(DRIVERCLASS);
}
// 釋放資源
public static void release(ResultSet rs, Statement stmt, Connection conn) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
rs = null;
}
release(stmt, conn);
}
public static void release(Statement stmt, Connection conn) {
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
stmt = null;
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn = null;
}
}
}
11点弯、PreparedStatement-防止SQL注入
-
SQL注入是用戶利用某些系統(tǒng)沒(méi)有對(duì)輸入數(shù)據(jù)進(jìn)行充分的檢查扇调,從而進(jìn)行惡意破壞的行為。
-
PreparedStatement是Statement的子接口抢肛,它的實(shí)例對(duì)象可以通過(guò)調(diào)用Connection.preparedStatement()方法獲得狼钮,相對(duì)于Statement對(duì)象而言:
PreperedStatement可以避免SQL注入的問(wèn)題。
Statement會(huì)使數(shù)據(jù)庫(kù)頻繁編譯SQL捡絮,可能造成數(shù)據(jù)庫(kù)緩沖區(qū)溢出熬芜。PreparedStatement 可對(duì)SQL進(jìn)行預(yù)編譯,從而提高數(shù)據(jù)庫(kù)的執(zhí)行效率锦援。
PreperedStatement對(duì)于sql中的參數(shù)猛蔽,允許使用占位符的形式進(jìn)行替換,簡(jiǎn)化sql語(yǔ)句的編寫灵寺。
-
示例:
public User login(User user) { // JDBC查詢 User existUser = null; Connection conn = null; PreparedStatement stmt = null; ResultSet rs = null; try { conn = JDBCUtils.getConnection(); String sql = "select * from users where name = ? and pwd = ?"; // 數(shù)據(jù)庫(kù)編譯時(shí) stmt = conn.prepareStatement(sql); // 將sql 發(fā)送給數(shù)據(jù)庫(kù)進(jìn)行編譯 // 設(shè)置參數(shù) stmt.setString(1, user.getName()); // or -- 傳入數(shù)據(jù)值曼库,不會(huì)作為關(guān)鍵字 --防止注入 stmt.setString(2, user.getPwd()); // 因?yàn)橹?將sql 傳遞數(shù)據(jù)庫(kù) rs = stmt.executeQuery(); // 如果登陸成功 只有一條記錄 if (rs.next()) { existUser = new User(); existUser.setId(rs.getInt("id")); existUser.setName(rs.getString("name")); existUser.setPwd(rs.getString("pwd")); existUser.setEmail(rs.getString("email")); } } catch (Exception e) { e.printStackTrace(); } return existUser; }
12、使用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):
executeBatch()方法:執(zhí)行批處理命令,將這組sql一次性發(fā)送數(shù)據(jù)庫(kù)
clearBatch()方法:清除批處理命令
-
示例:
Connection conn = null; Statement st = null; ResultSet rs = null; try { conn = JdbcUtil.getConnection(); String sql1 = "insert into person(name,password,email,birthday) values('kkk','123','abc@sina.com','1978-08-08')"; String sql2 = "update user set password='123456' where id=3"; st = conn.createStatement(); st.addBatch(sql1); //把SQL語(yǔ)句加入到批命令中 st.addBatch(sql2); //把SQL語(yǔ)句加入到批命令中 st.executeBatch(); } finally{ JdbcUtil.free(conn, st, rs); }
-
采用Statement.addBatch(sql)方式實(shí)現(xiàn)批處理:
優(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ǔ)句祭示,會(huì)導(dǎo)致數(shù)據(jù)庫(kù)編譯sql語(yǔ)句四次 ---- 性能比較差
。例如:Insert into user(name,password) values(‘a(chǎn)a’,’111’); Insert into user(name,password) values(‘bb’,’222’); Insert into user(name,password) values(‘cc’,’333’); Insert into user(name,password) values(‘dd’,’444’);
-
第二種方式谴古,PreparedStatement.addBatch():
如果連續(xù)執(zhí)行多條結(jié)構(gòu)相同sql --- 采用預(yù)編譯 ---- SQL只需要編譯一次
-
向數(shù)據(jù)庫(kù)插入50000條數(shù)據(jù)示例:
conn = JdbcUtil.getConnection(); String sql = "insert into person(name,password,email,birthday) values(?,?,?,?)"; st = conn.prepareStatement(sql); for(int i=0;i<50000;i++){ st.setString(1, "aaa" + i); st.setString(2, "123" + i); st.setString(3, "aaa" + i + "@sina.com"); st.setDate(4,new Date(1980, 10, 10)); st.addBatch(); if(i%1000==0){ st.executeBatch(); st.clearBatch(); } } st.executeBatch();
-
采用PreparedStatement.addBatch()實(shí)現(xiàn)批處理
優(yōu)點(diǎn):發(fā)送的是預(yù)編譯后的SQL語(yǔ)句质涛,執(zhí)行效率高。
缺點(diǎn):只能應(yīng)用在SQL語(yǔ)句相同掰担,但參數(shù)不同的批處理中汇陆。因此此種形式的批處理經(jīng)常用于在同一個(gè)表中批量插入數(shù)據(jù),或批量更新表的數(shù)據(jù)带饱。
13毡代、JavaEE體系結(jié)構(gòu)
-
MVC 和 JavaEE經(jīng)典三層結(jié)構(gòu) 由兩撥人分別提出的
三層結(jié)構(gòu)中業(yè)務(wù)層、數(shù)據(jù)持久層 ---Model
三層結(jié)構(gòu)中web層 Servlet ---Controller
三層結(jié)構(gòu)中web層 JSP ---View
-
JavaEE模式-DAO(Data Access Object)模式:
封裝對(duì)于數(shù)據(jù)源的操作
數(shù)據(jù)源可能是文件(如xml)、數(shù)據(jù)庫(kù)等任意存儲(chǔ)方式
負(fù)責(zé)管理與數(shù)據(jù)源的連接
負(fù)責(zé)數(shù)據(jù)的存仍绿恕(CRUD)
-
DAO 模式中的對(duì)象
Business Object:代表數(shù)據(jù)的使用者(業(yè)務(wù)層程序)
DataAccessObject:抽象并封裝了對(duì)底層數(shù)據(jù)源的操作(數(shù)據(jù)層程序)
DataSource:數(shù)據(jù)源(mysql數(shù)據(jù)庫(kù))
TransferObject:表示數(shù)據(jù)的Java Bean
BussinessObject 通過(guò) 將transferObject 傳遞 DataAccessObject 完成對(duì)DataSource的增刪改查
JDBC文集:
Java 與數(shù)據(jù)庫(kù)的橋梁——JDBC:http://www.reibang.com/p/c0acbd18794c
JDBC 進(jìn)階——連接池:http://www.reibang.com/p/ad0ff2961597
JDBC 進(jìn)階——元數(shù)據(jù):http://www.reibang.com/p/36d5d76342f1
JDBC框架——DBUtils:http://www.reibang.com/p/10241754cdd7