Java-JDBC調用批處理、預存程序、事務

來源:互聯網
上載者:User

標籤: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調用批處理、預存程序、事務

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.