Java事務(三),java事務
一. 為什麼使用ThreadLocal:
在上一篇博文中, 我們通過傳遞Connection的方式來控制事務, 這種方法可以達到目的, 但讓人看的不爽,
如果涉及到調用多個service, 那我是不是還得從controller層傳遞Connection?
ThreadLocal的用法見上一篇部落格, 該類保證一個類的執行個體變數在各個線程中都有一份單獨的拷貝,
從而不會影響其他線程中的執行個體變數
二. 如何使用ThreadLocal:
1. 寫一個TransactionManager類:
/** * 管理事務 */public class TransactionManager {private static ThreadLocal<Connection> local = new ThreadLocal<Connection>();// 開啟事務public static void beginTransaction() throws SQLException {Connection conn = JDBCUtils.getConnection();conn.setAutoCommit(false); // 將串連存入threadLocallocal.set(conn);}// 復原事務public static void rollback() throws SQLException {Connection conn = local.get();if (conn != null) {conn.rollback();conn.close();// 清空threadLocallocal.remove();}}// 提交事務public static void commit() throws SQLException {Connection conn = local.get();if (conn != null) {conn.commit();// 清空threadLocallocal.remove();}}// 關閉串連public static void close() throws SQLException {Connection conn = local.get();if (conn != null) {conn.close();// 清空threadLocallocal.remove();}}// 擷取資料庫連接public static Connection getConnection() {return local.get();}}使用ThreadLocal, 確保相同的線程擷取到的是同一個串連.
2.修改業務處理類
/** * 商務邏輯層 */public class AccountService {public void transfer(Account outAccount, Account inAccount, int money) throws SQLException {// 開啟 事務 TransactionManager.beginTransaction();// 查詢兩個賬戶AccountDAO accountDAO = new AccountDAO();outAccount = accountDAO.findAccountById(outAccount.getId());inAccount = accountDAO.findAccountById(inAccount.getId());// 轉賬 - 修改原賬戶金額 outAccount.setMoney(outAccount.getMoney() - money);inAccount.setMoney(inAccount.getMoney() + money);try {// 更新賬戶金額accountDAO.update(outAccount);accountDAO.update(inAccount);// 轉賬成功, 提交事務TransactionManager.commit();} catch (Exception e) {// 轉賬失敗, 復原事務TransactionManager.rollback();e.printStackTrace();} finally {// 關閉串連TransactionManager.close();}}}
使用TransactionManager來管理事務, 代碼變得更加簡潔.
3. 修改Dao類
/** * DAO層: CRUD */public class AccountDAO {// 查詢賬戶public Account findAccountById(int id) throws SQLException {String sql = "select * from account where id = ?";Object[] params = {id};QueryRunner queryRunner = new QueryRunner(JDBCUtils.getDataSource());return queryRunner.query(sql, new BeanHandler<Account>(Account.class), params);}// 更新賬戶public void update(Account account) throws SQLException {String sql = "update account set name = ?, money = ? where id = ?";Object[] params = {account.getName(), account.getMoney(), account.getId()};// 從threadLocal中擷取串連, 同一個線程拿到的是同一個串連Connection conn = TransactionManager.getConnection();QueryRunner queryRunner = new QueryRunner();queryRunner.update(conn, sql, params);}}
不需要傳遞Connection, 直接從TransactionManager中擷取串連.
三. 總結:
service和dao都是通過TransactionManager來擷取Connection, 同一個線程中, 它們在整個交易處理過程中使用了相同的Connection對象, 所以事務會處理成功, dao中沒有接受和業務無關的對象, 消除了api汙染, 另外使用TransactionManager來管理事務, 使service層的代碼變簡潔了.
java事務中有什
給你個連結mianshi.fenzhi.com/post/522.html 裡面介紹的很詳細!!
java交易處理
如果對資料庫進行多次操作,每一次的執行或步驟都是一個事務.如果資料庫操作在某一步沒有執行或出現異常而導致事務失敗,這樣有的事務被執行有的就沒有被執行,從而就有了事務的復原,取消先前的操作.....
JavaBean中使用JDBC方式進行交易處理
public int delete(int sID) {
dbc = new DataBaseConnection();
Connection con = dbc.getConnection();
try {
con.setAutoCommit(false);// 更改JDBC事務的預設提交方式
dbc.executeUpdate("delete from xiao where ID=" + sID);
dbc.executeUpdate("delete from xiao_content where ID=" + sID);
dbc.executeUpdate("delete from xiao_affix where bylawid=" + sID);
con.commit();//提交JDBC事務
con.setAutoCommit(true);// 恢複JDBC事務的預設提交方式
dbc.close();
return 1;
}
catch (Exception exc) {
con.rollBack();//復原JDBC事務
exc.printStackTrace();
dbc.close();
return -1;
}
}
在資料庫操作中,一項事務是指由一條或多條對資料庫更新的sql語句所組成的一個不可分割的工作單元。只有當事務中的所有操作都正常完成了,整個事務才能被提交到資料庫,如果有一項操作沒有完成,就必須撤消整個事務。
例如在銀行的轉帳事務中,假定張三從自己的帳號上把1000元轉到李四的帳號上,相關的sql語句如下:
update account set monery=monery-1000 where name='zhangsan'
update account set monery=monery+1000 where name='lisi'
這個兩條語句必須作為一個完成的事務來處理。只有當兩條都成功執行了,才能提交這個事務。如果有一句失敗,整個事務必須撤消。
在connection類中提供了3個控制事務的方法:
(1) setAutoCommit(Boolean autoCommit):設定是否自動認可事務;
(2) commit();提交事務;
(3) rollback();撤消事務;
在jdbc api中,預設的情況為自動認可事務,也就是說,每一條對資料庫的更新的sql語句代表一項事務,操作成功後,系統自動調用commit()來提交,否則將調用rollback()來撤消事務。
在jdbc api中,可以通過調用setAutoCommit(false) 來禁止自動認可事務。然後就可以把多條更新資料庫的sql語句做為一個事務,在所有操作完成之後,調用com......餘下全文>>