Java開啟事務操作數據庫


一、事務的四大特性(ACID)

1、原子性(atomicity):組成事務的語句形成了一個邏輯單元,不能只執行一部分;

2、一致性(consistency):在事務處理執行前后,數據庫與理論值是一致的(數據庫完整性約束);

3、隔離性(isolcation):一個事務處理和另一個事務處理相互間互不影響;

4、持續性(durability):事務處理的效果能夠被永久保存下來。

二、隔離級別

1、多線程並發執行可能會產生以下三個問題:

  臟讀(dirtyreads):一個事務讀取了另一個事務未提交的並行事務寫的數據;

  不可重復讀(non-repeatablereads):一個事務重新讀取前面讀取過的數據,發現該數據已經被另一個已提交的事務修改過;

  幻讀(phantomread):一個事務重新執行一個查詢,返回一套符合條件的行,發現這些行因為最近提交的事務而發生了改變

2、隔離級別

  讀未提交(Read uncommitted):未解決

  讀已提交 (Readcommitted):已解決:臟讀

  可重復讀 (Repeatableread):已解決:臟讀,不可重復讀

  序列化 (Serializble):已解決:臟讀,不可重復讀,幻讀

3、設置隔離級別

  connection.setTransactionlsolation(Connection.事務級別)

  MySql默認為度已提交;

三、基本操作

1、connection.setAutCommit(false):關閉事務自動提交

2、connection.commit():手動提交事務

3、connection.rollback():事務回滾

補:撤銷事務中的部分操作

SavePoint sp = connection.setSavepoint();:設置事務回滾點

connection.rollback(sp);

connection.commit();:最后不要忘了提交事務,否則前面需要提交保存的操作也將不會保存到數據庫中

代碼示例:(修改學生並更新班級)

StudentDao.java:

 1 public void updateStudent(Connection conn,Student s) throws SQLException{
 2         String sql = "update student set name = ?,age = ?,sex = ?,clazzid = ? where id = ?";
 3         try {
 4             st = conn.prepareStatement(sql);
 5             st.setString(1, s.getName());
 6             st.setInt(2, s.getAge());
 7             st.setString(3, s.getSex());
 8             st.setInt(4, s.getClazz().getId());
 9             st.setInt(5, s.getId());
10         } catch (SQLException e) {
11             e.printStackTrace();
12         }
13         /*上面只捕獲st = conn.prepareStatement(sql);的異常
14          * st.executeUpdate();最后將執行對數據庫更改的操作產生的異常拋出到上一層(Service)調用者
15          * connection開啟事務在Service中開啟
16          * 所以Connection來自Service中開啟事務的連接
17         */
18         st.executeUpdate();
19     }

ClazzDao.java:

 1 //為學生所轉到的新班級增加一個人數
 2     public void addClazzCount(Connection conn,int clazzid) throws SQLException{
 3         String sql = "update clazz set count = count + 1 where id =?";
 4         try {
 5             st = conn.prepareStatement(sql);
 6             st.setInt(1, clazzid);
 7         } catch (SQLException e) {
 8             e.printStackTrace();
 9         }
10         /*上面只捕獲st = conn.prepareStatement(sql);的異常
11          * st.executeUpdate();最后將執行對數據庫更改的操作產生的異常拋出到上一層(Service)調用者
12          * connection開啟事務在Service中開啟
13          * 所以Connection來自Service中開啟事務的連接
14         */
15         st.executeUpdate();
16     }
17     //為學生原來所在的班級減少一個人數
18     public void subClazzCount(Connection conn,int clazzid) throws SQLException{
19         String sql = "update clazz set count = count -1 where id =?";
20         try {
21             st = conn.prepareStatement(sql);
22             st.setInt(1, clazzid);
23         } catch (SQLException e) {
24             e.printStackTrace();
25         }
26         /*上面只捕獲st = conn.prepareStatement(sql);的異常
27          * st.executeUpdate();最后將執行對數據庫更改的操作產生的異常拋出到上一層(Service)調用者
28          * connection開啟事務在Service中開啟
29          * 所以Connection來自Service中開啟事務的連接
30         */
31         st.executeUpdate();
32     }

重點來了!

Service中開啟,提交,回滾事務

Service.java

 1     //更新學生信息
 2     public void update(Student s) {
 3         Connection connection = JDBCUtil_C3P0.getConnection();
 4         try {
 5             //關閉事務自動提交(開啟事務)
 6             connection.setAutoCommit(false);
 7             //在數據庫中查找學生原本所在班級
 8             int oldclazzid = studentDao.findById(s.getId()).getClazz().getId();
 9             //如果學生班級發生改變,對班級表進行修改
10             if(oldclazzid !=s.getClazz().getId()){
11                 //為轉到的新班級增加一個學生
12                 clazzDao.addClazzCount(connection, s.getClazz().getId());
13                 //為原本所在的舊班級減少一個學生
14                 clazzDao.subClazzCount(connection, oldclazzid);
15                 //測試事務,手動拋出一個SQL異常
16                 //throw new SQLException("操作異常");
17             }
18             //修改學生信息
19             studentDao.updateStudent(connection, s);
20             //以上所有操作無異常則提交事務
21             connection.commit();
22             
23         } catch (SQLException e) {
24             e.printStackTrace();
25             //一旦事務中有哪一步操作發生異常則進行事務回滾
26             try {
27                 connection.rollback();
28             } catch (SQLException e1) {
29                 e1.printStackTrace();
30             }
31         }finally{
32             //關閉連接資源
33             clazzDao.close(connection);
34             studentDao.close(connection);
35         }
36         
37     }

Over


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM