JDBC執(zhí)行數(shù)據(jù)庫操作語句,首先需要將sql語句打包成為網(wǎng)絡(luò)字節(jié)流,傳遞給數(shù)據(jù)庫,數(shù)據(jù)庫經(jīng)過解包,然后編譯sql語句,最后執(zhí)行,然后將結(jié)果通過字節(jié)流的形式返回給JDBC API
成都創(chuàng)新互聯(lián)公司是工信部頒發(fā)資質(zhì)IDC服務(wù)器商,為用戶提供優(yōu)質(zhì)的綿陽主機托管服務(wù)
簡單的來說大致分為以下幾點:
JDBC打包sql語句
發(fā)送字節(jié)流至數(shù)據(jù)庫
數(shù)據(jù)庫解包
檢查sql語法,編譯sql
執(zhí)行sql語句
注冊驅(qū)動 (Driver)
建立連接(創(chuàng)建Connection)
創(chuàng)建執(zhí)行sql語句(通常是創(chuàng)建Statement或者其子類)
執(zhí)行語句
處理執(zhí)行結(jié)果(在非查詢語句中,該步驟是可以省略的)
案例
@Test
public void wholeExample(){
try {
//1.注冊驅(qū)動
Class.forName("com.MySQL.jdbc.Driver");
//2.獲取數(shù)據(jù)庫連接
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root","123456");
//3.創(chuàng)建執(zhí)行句柄
Statement stmt = conn.createStatement();
//4.執(zhí)行sql語句
ResultSet rs = stmt.executeQuery("select * from user");
//5.處理執(zhí)行結(jié)果
while(rs.next()){
System.out.println("id:"+rs.getInt(1)+"\tname:"+rs.getString(2)+"\tbirthday:"+rs.getDate(3)+"\tmoney:"+rs.getFloat(4));
}
//6.釋放資源
rs.close();
stmt.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
當(dāng)我們存放大量的文本信息時,數(shù)據(jù)庫中的varchar或者varchar2肯定是不能滿足的,varchar2好像最多只能有4000個長度,存放一篇很長的文章或者一個文本信息,我們采用CLOB類型
針對二進(jìn)制文件進(jìn)行的存取,比如圖片,音頻等信息
//stream文件流
PreparedStatement.setBlob(index, stream)
數(shù)據(jù)庫的事務(wù)是保證數(shù)據(jù)完整性的一種機制,簡而言之,就是怎樣確保數(shù)據(jù)的執(zhí)行過程要么都成功,要么都失敗
原子性(atomicity):組成事務(wù)處理的語句形成了一個邏輯單元,不能只執(zhí)行其中的一部分
一致性(consistency):在事務(wù)處理執(zhí)行前后,數(shù)據(jù)庫是一致的(兩個賬戶要么都變,或者都不變)
隔離性(isolcation):一個事務(wù)處理對另一個事務(wù)處理沒有影響
Jdbc的事務(wù)默認(rèn)是打開的,也就是說執(zhí)行每一步操作的話,事務(wù)都會隱式的進(jìn)行提交,在拋出異常之前,我們的更改操作已經(jīng)同步到了數(shù)據(jù)庫中去
//提交事務(wù)
//回滾事務(wù)
通常所說的跨庫事務(wù),要求幾個數(shù)據(jù)庫的事務(wù)在一個應(yīng)用中保持一致,JTA就是為了解決這個問題而誕生的
在數(shù)據(jù)庫操作中PreparedStatement會帶來很大的方便,減少拼寫sql字符串帶來的麻煩,防止SQL注入的發(fā)生.
PreparedStatement是Statement的子類
在數(shù)據(jù)庫操作中調(diào)用數(shù)據(jù)庫中的存儲過程
案例:執(zhí)行有參數(shù)有返回值的存儲過程
create or replace procedure test1(in id integer,in name varchar(20),in money float,out counter integer)
as
begin
insert into user values(id,name,now(),money);
select count(1) into counter from user;
commit;
end test1;
@Test
public void callProcedureWithParamWithResult() throws SQLException{
Connection conn = null;
CallableStatement stmt = null;
ResultSet rs = null;
try {
conn = ConnCreate.getConnection("jdbc:mysql://localhost:3306/test",
"root", "123456");
String sql = "{call test1(?,?,?,?)}";
stmt = conn.prepareCall(sql);
stmt.setInt(1, 17);
stmt.setString(2, "test");
stmt.setFloat(3, 6000);
stmt.registerOutParameter(1, Types.INTEGER);
stmt.executeUpdate();
int counter = stmt.getInt(4);
System.out.println(counter);
} finally {
ConnCreate.close(conn, stmt, rs);
}
}
//添加一條條的sql
// 執(zhí)行批處理
利用sql語句進(jìn)行分頁(eg: mysql的limit ? ?, 一個offsize偏移量,另一個pagesize頁面數(shù)量)
@Test
public void page() throws SQLException{
page(100,20);
}
static void page(int start,int total) throws SQLException{
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
conn = ConnCreate.getConnection("jdbc:mysql://localhost:3306/test",
"root", "123456");
String sql = "select * from user limit ?,?";
stmt = conn.prepareStatement(sql);
stmt.setInt(1, start);
stmt.setInt(2, total);
rs = stmt.executeQuery();
while(rs.next()) //向下滾動
{
System.out.println("name:"+rs.getString(2)+"id:"+rs.getInt(1));
}
} finally {
ConnCreate.close(conn, stmt, null);
}
}
使用jdbc最大的開銷之一就是創(chuàng)建數(shù)據(jù)庫,當(dāng)我們頻繁的創(chuàng)建數(shù)據(jù)庫時,勢必影響應(yīng)用的效率,或者在數(shù)據(jù)庫關(guān)閉出現(xiàn)問題時,我們不能馬上釋放,時間長一些,整個數(shù)據(jù)庫的 資源將會被我們的應(yīng)用耗盡
C3P0
如果我們不知道我們的一個sql語句查詢了幾列結(jié)果集,并且每列的列名,類型等信息,這個時候我們應(yīng)該使用ResultSetMetaData
@Test
public void resultMeta() throws SQLException{
String sql="select * from user";
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
conn = ConnFactory.getConnection();
stmt = conn.prepareStatement(sql);
rs = stmt.executeQuery();
ResultSetMetaData rsmd = rs.getMetaData();
int count = rsmd.getColumnCount();
for(int i=1;i<=count;++i){
System.out.println("Type:"+rsmd.getColumnType(i));
System.out.println("ColumnName:"+rsmd.getColumnName(i));
System.out.println("ColumnLable:"+rsmd.getColumnLabel(i));
}
} finally{
ConnFactory.close(conn, stmt, rs);
}
}