java service 事物_Service 事务(JdbcUtils 升级)
1. DAO 事務
// 在 DAO 中處理事務真是"小菜一碟"
public void xxx(){
Connection con = null;
try{
con = JdbcUtils.getConnection();
con.setAutoCommit(false); // 開啟事務
QueryRunner qr = new QueryRunner();
String sql = ...;
Object[] params = ...;
qr.update(con,sql,params);
sql = ...;
Object[] params = ...;
qr.update(con,sql,params);
con.commit(); // 提交事務
} catch(Exception e){
try{
// 回滾事務
if(con != null) {con.rollback();}
}catch(Exception e){}
}finally{
try{
con.close();
}catch(Exception e){}
}
}
2. Service 才是處理事務的地方
DAO 中不是處理事務的地方,因為 DAO 中的每個方法都是對數據庫的一次操作, 而 Service 中的方法才是
對應一個業務邏輯,也就是我們需要在 Service 中的一方法中調用 DAO 的多個方法,而這些方法應該在一個
事務中.
// 事務需要保證為同一個 Connection
// 可以通過向 DAO 中傳遞 Connection, 來保證 DAO 的多個方法使用相同的 Connection
public class XXXService(){
private XXXDao dao = new XXXDao();
public void serviceMethod(){
// 但是 Connection 對象只能出現在 DAO 中, 因為它是 JDBC 的東西,
// JDBC 的東西是用來連接數據庫的, 連接數據庫是由 DAO負責, 而事務卻
// 應該由 Service 負責.
Connection con = null;
try{
con = JdbcUtils.getConnection();
con.setAutoCommit(false);
// 向 DAO 中傳遞 Connection
dao.daoMethod2(con,...);
dao.datMethod3(con,...);
con.commit();
}catch(Exception e){
try{
con.rollback();
} catch(Exception e){}
}finally{
try{
con.close();
}catch(Exception e){}
}
}
}
3. 修改 JdbcUtils
把對事物的開啟和關閉放到 JdbcUtils 中,在 Service 中調用 JdbcUtils 的方法來完成事務的處理,
但在 Service 中就不會再出現 Connection 了.
DAO 中的方法不用再讓 Service 來傳遞 Connection 了, DAO 會主動從 JdbcUtils 中獲取 Connection
對象, 這樣, JdbcUtils 成為了 DAO 和 Service 的中介!
// Service 中的代碼
public class XXXService(){
private XXXDao dao = new XXXDao();
public void serviceMethod(){
try{
JdbcUtils.beginTransaction();
dao.daoMethod2();
dao.daoMethod3();
JdbcUtils.commitTransaction();
}catch(Exception e){
JdbcUtils.rollbackTransaction();
}
}
}
// JdbcUtils 代碼
public class JdbcUtils{
private static ComboPooledDataSource dataSource = new ComboPooledDataSource();
// 它是事務專用連接, 并且每個線程分配一個Connection
private static ThreadLocal tl = new ThreadLocal();
public static Connection getConnection() throws SQLException{
Connection con = tl.get(); // 獲取當前線程的 con
// 當 con 不等于 null, 說明已經調用過 beginTransaction() 方法了.表示開啟了事務.
if(con != null) return con;
return dataSource.getConnection();
}
public static DataSource getDataSource(){
return dataSource();
}
// 添加開啟事務的方法
// 獲取一個 Connection, 設置它的 setAutoCommit(false)
// 還要保證 DAO 中使用的連接是我們剛剛創建的!!
/*
* 1. 創建一個 Connection, 設置為手動提交
* 2. 把這個 Connection 給 DAO 用!
* 3. 還要讓 commitTransaction 或 rollbackTransaction 可以獲取到!!
*/
public static void beginTransaction() throws SQLException {
Connection con = tl.get();
if(con != null) throw new SQLException("已經開啟了事務,就不要重復開啟了!");
con = getConnection(); // 給 con 賦值, 表示事務已經開啟了.
con.setAutoCommit(false);
tl.set(con); // 把當前線程的連接保存起來.
}
// 添加提交事務的方法
// 獲取 beginTransaction 提供的 Connection, 然后調用 commit 方法
public static void commitTransaction() throws SQLException {
Connection con = tl.get(); // 獲取當前線程的專用連接
if(con == null) throw new SQLException("還沒有開啟事務,不能提交!");
con.commit();
con.close();
// 把它設置為 null, 表示事務已經結束了.
// 下次再去調用 getconnection(),返回的就不是 con 了.
// con = null; 因為有了線程, 所以將 con 直接從線程中移除即可
tl.remove(); // 從 tl 中移除連接
}
// 添加回滾事務的方法
// 獲取 beginTransaction 提供的 Connection, 然后調用 rollback 方法.
public static void rollbackTransaction() throws SQLException {
Connection con = tl.get(); // 獲取當前線程的專用連接
if(con == null) throw new SQLException("還沒有開啟事務,不能回滾!");
con.rollback();
con.close();
tl.remove();
}
// 釋放連接
public static void releaseConnection(Connection con) throws SQLException{
Connection con = tl.get(); // 獲取線程中的事務
// 判斷 connection 是不是事務專用, 如果是, 就不關閉
// 如果不是事務專用, 那么就要關閉
// con 是事務專用連接, 如果 con 為 null,表示沒有事務.
// 那么, connection 肯定不是事務專用的.
if(con == null) connection.close();
// 如果 con != null, 說明有事務,那么需要判斷參數連接是否與 con 相等,
// 如果不相等, 說明 connection 不是事務專用連接.
if(con != connection) connection.close();
}
}
// DAO 層代碼
public class AccountDao{
public void update(String name, double money) throws SQLException{
QueryRunner qr = new QueryRunner();
String sql = "UPDATE account SET balance=balance+? WHERE name=?";
Object[] params = {money,name};
// 我們需要自己來提供連接, 保證在同一事務中, 多次調用使用的是同一個連接!!
Connection con = JdbcUtils.getConnection();
qr.update(con,sql,params);
// 關閉連接
JdbcUtils.releaseConnection(connection);
}
}
參考資料:
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的java service 事物_Service 事务(JdbcUtils 升级)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java调用scilab_Java调用S
- 下一篇: 线性表总结