05.JDBC編程之處理存儲過程&Transaction
一、存儲過程處理
1.存儲過程 概念類似與函數,就是把一段代碼封裝起來。當要執行這一段代碼的時候,可以通過調用該存儲過程來實現。在封裝的語句體裡面,可以用if/else、case、while等控制結構(參數、控制結構、循環),可以進行sql編程。
(1)sql語法 a.查看現有的存儲過程 show procedure status \G b.創建存儲過程 delimiter $ //修改語句結束符 create procedure 存儲過程名字(參數列表) begin 封裝sql的語句 end$ c.刪除存儲過程 drop procedure 存儲過程名字; d.調用存儲過程 call 存儲過程名字()$ call 存儲過程名字(參數)$
(2)存儲過程實例 在MySQL終端預先創建一個存儲過程-計算1+2+3+...+100的和 create procedure pro(nam char(10),n smallint) begin declare i int; declare s int; set i=1; set s=0; while i<=n do set s=s+i; set i=i+1; end while; insert into test(name,age,score) values(nam,0,s) ; end$ 注: ◇declare 聲明一個變量 ◇set 設置變量的值 ◇select 輸出/查看某個變量或列 ◇存儲過程名只有用單個字符
2.JDBC處理存儲過程 CallableStatement 對象為所有的DBMS 提供了一種以標准形式調用已儲存過程的方法。已儲存過程儲存在數據庫中。對已儲存過程的調用是 CallableStatement對象所含的內容。這種調用是 用一種換碼語法來寫的,有兩種形式:一種形式帶結果參,另一種形式不帶結果參數。結果參數是 一種輸出 (OUT) 參數,是已儲存過程的返回值。兩種形式都可帶有數量可變的輸入(IN 參數)、 輸出(OUT 參數)或輸入和輸出(INOUT 參數)的參數。問號將用作參數的占位符。 CallableStatement 對象是用 Connection 方法 prepareCall 創建的,應用代碼如下:
CallableStatement callStmt=conn.prepareCall("call pro(?,?)");
//調用Connection對象的prepareCall方法獲取CallableStatement對象 callStmt.setString(1, "pro");
//向第一個占位符參數,賦值nam='pro' callStmt.setInt(2, 100);
//向第二個占位符,賦值為n=100 callStmt.execute();
//執行sql語句
3.源碼實戰 (1)創建存儲過程 該存儲過程完成計算1+2+3+...+100的和,並將求和結果作為score值插入到表中。
(2)編寫JDBC數據庫應用程序調用該存儲過程
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
/*MySQL數據庫編程
* 實例(6):JDBC批量處理存儲過程*/
public class JDBC_Procedure {
public static void main(String[] args) {
//0.連接數據庫相關參數
String url="jdbc:mysql://localhost:3306/jdbc_test_db"; //數據庫URL(資源定位唯一標識符)
String DBusername="root"; //數據庫用戶名
String DBpasswd="111111"; //數據庫密碼
//1.加載數據庫驅動,將Driver注冊到DriverManager中
try{
Class.forName("com.mysql.jdbc.Driver");
}catch(ClassNotFoundException e){
e.printStackTrace();
}
//2.通過數據庫URL連接到數據庫
Connection conn=null;
CallableStatement callStmt=null;
try{
//3.獲得表示連接到數據庫的Connection對象
conn=DriverManager.getConnection(url, DBusername, DBpasswd);
//4.獲取執行存儲過程SQL語句的CallableStatement對象
callStmt=conn.prepareCall("call pro(?,?)");
callStmt.setString(1, "pro"); //向第一個占位符參數,賦值nam='pro'
callStmt.setInt(2, 100); //向第二個占位符,賦值為n=100
callStmt.execute(); //執行sql語句
}catch(SQLException e){
e.printStackTrace();
}
//5.釋放JDBC資源
if(callStmt!=null) //關閉聲明
{
try{
callStmt.close();
}catch(SQLException e){
e.printStackTrace();
}
}
if(conn!=null) //關閉連接
{
try{
conn.close();
}catch(SQLException e){
e.printStackTrace();
}
}
}
}
運行結果
二、事物(Transaction)處理 1.事物(Transaction) 事物是指一組操作,要麼都成功執行,要麼都不執行。事物有原子性、隔離性、一致性、持久性四大ACID特性。 (1)原子性(Atomicity):原子意為最小粒子,或者說不能再分的事物。數據庫事物的不可再分的原 則即為原子性; (2)一致性(Consistency):事物發生前和發生後,數據的總額依然匹配; (3)隔離性(Isolation):在所有的操作沒有執行完畢之前,其他會話不能夠看到中間改變的過程; (4)持久性(Durability):事物產生的影響不能夠撤銷,如果除了錯誤,事物也不允許撤銷,只能通過"補償性事物"
2.事物的用法 第一步:開啟事物語句 start transaction; 第二步:執行sql操作,即普通sql操作;
第三步:提交事物或者撤銷操作,事物結束(下次使用事物需重新開啟) commit;或者rollback; 注意:有一些語句會造成事物的隱式提交,如重復執行start transaction。另外,建表的時候選擇innodb引擎。
3.JDBC處理存儲過程
(1)由於JDBC對事物的處理,默認是自動提交事物; 所以,在執行SQL語句之前,我們先調用Connection對象的setAutoCommit()並傳入false參數。 Connection conn=DriverManager.getConnection(url, DBusername, DBpasswd); conn.setAutoCommit(false);
(2)添加需要處理的SQL語句,最後調用Connection對象的commit方法提交事物,使SQL語句生效。
Statement stmt=conn.createStatement(); stmt=conn.createStatement();
stmt.addBatch("insert into test(name,age,score) values('haha',10,33)");
stmt.executeBatch(); //批量執行SQL語句
conn.commit(); //提交事物
conn.setAutoCommit(true);
4.源碼實戰
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class JDBC_Transaction {
/*MySQL數據庫編程
* 實例(7):JDBC批量處理事物Transaction*/
public static void main(String[] args) {
//0.連接數據庫相關參數
String url="jdbc:mysql://localhost:3306/jdbc_test_db"; //數據庫URL(資源定位唯一標識符)
String DBusername="root"; //數據庫用戶名
String DBpasswd="896013"; //數據庫密碼
//1.加載數據庫驅動,將Driver注冊到DriverManager中
try{
Class.forName("com.mysql.jdbc.Driver");
}catch(ClassNotFoundException e){
e.printStackTrace();
}
//2.通過數據庫URL連接到數據庫
Connection conn=null;
Statement stmt=null;
try{
//3.獲得表示連接到數據庫的Connection對象
conn=DriverManager.getConnection(url, DBusername, DBpasswd);
//4.設置SQL語句不自動執行
conn.setAutoCommit(false);
//5.獲取Statement對象
stmt=conn.createStatement();
stmt.addBatch("insert into test(name,age,score) values('haha',10,33)");
stmt.addBatch("insert into test(name,age,score) values('heihei',11,44)");
stmt.addBatch("insert into test(name,age,score) values('xixi',14,55)");
stmt.executeBatch(); //批量執行SQL語句
conn.commit(); //提交事物
conn.setAutoCommit(true);
}catch(SQLException e){
e.printStackTrace();
}
//5.釋放JDBC資源
if(stmt!=null) //關閉聲明
{
try{
stmt.close();
}catch(SQLException e){
e.printStackTrace();
}
}
if(conn!=null) //關閉連接
{
try{
conn.close();
}catch(SQLException e){
e.printStackTrace();
}
}
}
}
運行結果: (1)注釋事物提交語句 //conn.commit(); // conn.setAutoCommit(true);
(2)執行conn.commit()結果