標籤:io os ar 使用 java for strong sp 檔案
一、使用Batch批量處理資料庫
當需要向資料庫發送一批SQL語句執行時,應避免向資料庫一條條的發送執行,而應採用JDBC的批處理機制,以提升執行效率。;
1、實現批處理有兩種方式,第一種方式:
Statement.addBatch(sql) list
執行批處理SQL語句
executeBatch()方法:執行批處理命令
clearBatch()方法:清除批處理命令
例:
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try {
conn = JDBCManager.getConnection();
String sql1 = "insert into user(name,password,email,birthday)
values(‘kkk‘,‘123‘,‘[email protected]‘,‘1978-08-08‘)";
String sql2 = "update user set password=‘123456‘ where id=3";
st = conn.createStatement();
st.addBatch(sql1); //把SQL語句加入到批命令中
st.addBatch(sql2); //把SQL語句加入到批命令中
st.executeBatch();
} finally{
JDBCManager.DBclose(con,st,rs);
}
採用Statement.addBatch(sql)方式實現批處理:
優點:可以向資料庫發送多條不同的SQL語句。
缺點:
SQL語句沒有先行編譯。
當向資料庫發送多條語句相同,但僅參數不同的SQL語句時,需重複寫上很多條SQL語句。例如:
Insert into user(name,password) values(‘aa’,’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’);
2、實現批處理的第二種方式:
PreparedStatement.addBatch();
例:
conn = JDBCManager.getConnection();//擷取工具;
String sql = "insert into user(name,password,email,birthday) values(?,?,?,?)";
st = conn.prepareStatement(sql);//預先處理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();//將一組參數添加到此 PreparedStatement 對象的批處理命令中。
if(i%1000==0){
st.executeBatch();
st.clearBatch();清空此 Statement 對象的當前 SQL 命令列表。
}
}
st.executeBatch();將一批命令提交給資料庫來執行,如果全部命令執行成功,則返回更新計數組成的數組。返回數組的 int 元素的排序對應於批中的命令,批中的命令根據被添加到批中的順序排序
採用PreparedStatement.addBatch()實現批處理
優點:發送的是先行編譯後的SQL語句,執行效率高。
缺點:只能應用在SQL語句相同,但參數不同的批處理中。因此此種形式的批處理經常用於在同一個表中批量插入資料,或批次更新表的資料。
二、獲得資料庫自動產生的主鍵:
Connection con=null;
PreparedStatement ps=null;
con = JDBCManager.getConnection();
String sql="insert into users(name,password) values(?,?)";
try {
ps = con.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);//擷取返回的主鍵;
ps.setString(1, "qq");
ps.setString(2, "123");
ps.executeUpdate();
ResultSet rs=ps.getGeneratedKeys();//返回一個結果集,儲存著產生的key的結果集,
while(rs.next()){
System.out.println(rs.getObject(1));//結果集只有一個值;
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
JDBCManager.DBclose(con, ps, null);
}
三、JDBC調用預存程序
預存程序的建立
create procedure 預存程序名(參數)
預存程序體
編寫一個預存程序,查詢學生表中的所有資訊。
delimiter $$
create procedure myproc1()
begin
select * form xs;
end $$
delimiter ;
執行:call myproc1();
參數
in :輸入參數
out: 輸出參數
inout:輸入輸出參數
要求:編寫一個預存程序,通過學號查詢某學生的資訊。
delimiter $$
create procedure select_student(in xh char(6))
begin
select * from xs where 學號=xh;
end $$
delimiter ;
執行:call select_student(‘081101‘);
要求:編寫一個預存程序,統計學生的總人數
delimiter $$
create procedure count_xs(out number int)
begin
select count(*) into number from xs;
end $$
delimiter ;
執行:call count_xs(@rs);
查詢: select @rs;
create procedure 預存程序名(in|out|inout 參數名 類型。。。。);
JDBC調用存數過程(建立好預存程序體):
當值是輸入函數時:
例:
Connection con=null;
CallableStatement cs=null;
con=JDBCManager.getConnection();
try {
cs=con.prepareCall("{call pd(?,?)}");//預存程序語句;
cs.setString(1, "yy");
cs.setString(2, "msn");
cs.execute();//執行
System.out.println("執行成功");
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
JDBCManager.DBclose(con, cs, null);
}
當輸入和輸出同時:
例
Connection con=null;
CallableStatement cs=null;
con=JDBCManager.getConnection();
try {
cs=con.prepareCall("{call pcall(?,?)}");
cs.setInt(1, 10);
cs.registerOutParameter(2,Types.CHAR);//擷取一下註冊類型;
cs.execute();//執行
System.out.println(cs.getString(2));//擷取第二個String類型的參數值;
cs.execute();
System.out.println("執行成功");
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
JDBCManager.DBclose(con, cs, null);
}
四、事務的使用
事務指邏輯上的一組操作,組成這組操作的各個單元,要不全部成功,要不全部不成功。
例如:A——B轉帳,對應於如下兩條sql語句
update from account set money=money+100 where name=‘b’;
update from account set money=money-100 where name=‘a’;
資料庫開啟事務命令
start transaction 開啟事務
Rollback 復原事務
Commit 提交事務
當Jdbc程式向資料庫獲得一個Connection對象時,預設情況下這個Connection對象會自動向資料庫提交在它上面發送的SQL語句。若想關閉這種預設提交方式,讓多條SQL在一個事務中執行,可使用下列語句:
JDBC控制事務語句
Connection.setAutoCommit(false); start transaction
Connection.rollback(); rollback
Connection.commit(); commit
建立JDBC的事務主要分以下步驟
1.設定事務的提交方式為非自動認可:
conn.setAutoCommit(false);
2.將需要添加事務的代碼放入try,catch塊中。
3.在try塊內添加事務的提交操作,表示操作無異常,提交事務。
conn.commit();
4.在catch塊內添加復原事務,表示操作出現異常,撤銷事務:
conn.rollback();
5.設定事務提交方式為自動認可:
conn.setAutoCommit(true);
事務的特性(ACID)
原子性(Atomicity)
原子性是指事務是一個不可分割的工作單位,事務中的操作要麼都發生,要麼都不發生。
一致性(Consistency)
事務必須使資料庫從一個一致性狀態變換到另外一個一致性狀態。
隔離性(Isolation)
事務的隔離性是多個使用者並發訪問資料庫時,資料庫為每一個使用者開啟的事務,不能被其他事務的操作資料所幹擾,多個並發事務之間要相互隔離。
持久性(Durability)
持久性是指一個事務一旦被提交,它對資料庫中資料的改變就是永久性的,接下來即使資料庫發生故障也不應該對其有任何影響。
事務的隔離性:
髒讀:
指一個事務讀取了另外一個事務未提交的資料。
這是非常危險的,假設A向B轉帳100元,對應sql語句如下所示
1.update account set money=money+100 while name=‘b’;
2.update account set money=money-100 while name=‘a’;
當第1條sql執行完,第2條還沒執行(A未提交時),如果此時B查詢自己的帳戶,就會發現自己多了100元錢。如果A等B走後再復原,B就會損失100元。
不可重複讀取:
在一個事務內讀取表中的某一行資料,多次讀取結果不同。
例如銀行想查詢A帳戶餘額,第一次查詢A帳戶為200元,此時A向帳戶存了100元並提交了,銀行接著又進行了一次查詢,此時A帳戶為300元了。銀行兩次查詢不一致,可能就會很困惑,不知道哪次查詢是準的。
和髒讀的區別是,髒讀是讀取前一事務未提交的髒資料,不可重複讀取是重新讀取了前一事務已提交的資料。
很多人認為這種情況就對了,無須困惑,當然是後面的為準。我們可以考慮這樣一種情況,比如銀行程式需要將查詢結果分別輸出到電腦螢幕和寫到檔案中,結果在一個事務中針對輸出的目的地,進行的兩次查詢不一致,導致檔案和螢幕中的結果不一致,銀行工作人員就不知道以哪個為準了。
虛讀(幻讀)
是指在一個事務內讀取到了別的事務插入的資料,導致前後讀取不一致。
如丙存款100元未提交,這時銀行做報表統計account表中所有使用者的總額為500元,然後丙提交了,這時銀行再統計發現帳戶為600元了,造成虛讀同樣會使銀行不知所措,到底以哪個為準。
資料庫共定義了四種隔離等級:
Serializable:可避免髒讀、不可重複讀取、虛讀情況的發生。(序列化)(序列化)
Repeatable read:可避免髒讀、不可重複讀取情況的發生。(可重複讀)
Read committed:可避免髒讀情況發生(讀已提交)。
Read uncommitted:最低層級,以上情況均無法保證。(讀未提交)
set transaction isolation level 設定交易隔離等級
select @@tx_isolation 查詢當前交易隔離等級
例:
Connection con=null;
PreparedStatement st=null;
String sql1="insert into users(name,password) values(‘bbbbb‘,‘bbbb‘)";
String sql2="delete from users where id=9";
try {
con=DBManager.getConnection();
con.setAutoCommit(false);//把自動認可方式變為人工
st=con.prepareStatement(sql1);
st.executeUpdate();
System.out.println("第一個語句成功了");
st=con.prepareStatement(sql2);
st.executeUpdate();
System.out.println("第二個語句成功了");
con.commit();
} catch (Exception e) {
try {
con.rollback();//出現異常進行復原;
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
e.printStackTrace();
}finally{
try {
con.setAutoCommit(true);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
DBManager.closeDB(con, st, null);
}
Java-JDBC調用批處理、預存程序、事務