日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

手工實(shí)現(xiàn)JDBC事務(wù)管理。--火狐

 飄飄 2007-04-24

手工實(shí)現(xiàn)JDBC事務(wù)管理。

[ 2006-4-29 12:41:06 | By: foxty ]

  最近由于項(xiàng)目原因,底層數(shù)據(jù)庫訪問都必須使用JDBC來操作,為了能更好的實(shí)現(xiàn)事務(wù),而且也便于將來移植到Ibatis上去,在作設(shè)計(jì)的時(shí)候參照Ibatis的Dao模式來設(shè)計(jì)dao,然后事務(wù)控制就必須得自己手工來實(shí)現(xiàn)了。并且一起也實(shí)現(xiàn)了事務(wù)得嵌套。主要依靠2個(gè)類來實(shí)現(xiàn)。

    1,TransactionUtil類,負(fù)責(zé)開啟事務(wù),提交事務(wù)以及關(guān)閉事務(wù)。

    2,Transaction類,用來記錄當(dāng)前事務(wù)得狀態(tài)以及數(shù)據(jù)庫連接。

  

 package com.orizone.oa.extra.service;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import net.orizone.oa.common.ConnectionPoolBean;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.orizone.comm.util.BusinessException;

public class TransactionUtil
{
 private final static ThreadLocal local = new ThreadLocal();
 private static Log log = LogFactory.getLog(TransactionUtil.class);
 
 /**
  * 開啟事務(wù)
  */
 public static void startTransaction()throws  BusinessException
 {
  Transaction tran = (Transaction)local.get();
  //判斷此事務(wù)是否屬于一個(gè)頂層事務(wù)。
  if(tran == null)
  {
   tran = new Transaction();
   //設(shè)置本地線程的connection
   Connection con = ConnectionPoolBean.getConnection();
   try
   {
    con.setAutoCommit(false);
   }catch(SQLException e)
   {
    e.printStackTrace();
    throw new BusinessException(e, "開啟事務(wù)失?。?);
   }
   tran.setConnection(con);
   tran.setCommitCount(0);
   tran.setTransCount(1);
   tran.setTransDeep(1);
   
   local.set(tran);
  }else
  {
   //事務(wù)已經(jīng)開啟,將嵌套層次深度加一,將事務(wù)次數(shù)加一
   tran.setTransCount(tran.getTransCount() + 1);
   tran.setTransDeep(tran.getTransDeep() + 1);
  }  
 }
 
 /**
  * 提交事務(wù)
  *
  */
 public static void commitTransaction()throws  BusinessException
 {
  Transaction tran = (Transaction)local.get();
  //如果事務(wù)屬于嵌套,則不提交數(shù)據(jù),直接將層次數(shù)減一。
  if(tran.getTransDeep() > 1)
  {
   tran.setTransDeep(tran.getTransDeep() - 1);
   tran.setCommitCount(tran.getCommitCount() + 1);
   return;
  }
  
  Connection con = tran.getConnection();
  try
  {
   if(tran.hasFullExecute())
   {
    con.commit();   
   }
  }catch(SQLException e)
  {
   log.error(e);   
   throw new BusinessException(e, "提交事務(wù)失敗!");
  }
 }
 
 /**
  * 結(jié)束事務(wù)
  *
  */
 public static void endTransaction()throws  BusinessException
 {
  Transaction tran = (Transaction)local.get();
  //如果事務(wù)屬于嵌套,則不關(guān)閉連接,直接將層次數(shù)減一。
  if(tran.getTransDeep() > 1)
  {
   tran.setTransDeep(tran.getTransDeep() - 1);
   return;
  }
  
  //當(dāng)前事務(wù)已經(jīng)結(jié)束,清空ThreadLocal變量,防止下一次操作拿到已經(jīng)關(guān)閉的Connection對象。
  local.set(null);
  Connection con = tran.getConnection();
  try
  {
   if(!tran.hasFullExecute())
   {
    con.rollback();
   }
  }catch(SQLException e)
  {
   log.error(e);
   throw new BusinessException(e, "事務(wù)回滾失敗!");
  }finally
  {
   try
   {
    con.close();
   }catch(SQLException se)
   {
    log.error(se);
    throw new BusinessException(se, "關(guān)閉事務(wù)失敗!");
   }
  }
  
 }
 
 /**
  * 獲取當(dāng)前事務(wù)的數(shù)據(jù)庫連接。
  * @return
  */
 public static Connection getConnection()
 {
  Transaction tran = (Transaction)local.get();
  Connection  con = tran.getConnection();
  if(con == null)
  {
   con = ConnectionPoolBean.getConnection();   
  }
  return con;
 }
 
 /**
  * 測試代碼
  * @param args
  * @throws Exception
  */
 public static void main(String args[])throws Exception
 {
  test();
  test();
 }
 
 /**
  * 測試代碼
  *
  */
 private static void test()
 {
  TransactionUtil.startTransaction();
  try
  {
   Connection con = TransactionUtil.getConnection();
   Statement stmt = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
   stmt.executeUpdate("INSERT INTO bb(bb) values(‘bb‘)");
   stmt.executeUpdate("INSERT INTO aa(aa) values(‘a(chǎn)a‘)");
   //if(true) throw new Exception("");
   TransactionUtil.commitTransaction();
  }catch(Exception e)
  {
   e.printStackTrace();
   //throw new BusinessException("");
  }finally
  {
   TransactionUtil.endTransaction();
  }
 }
}

 

package com.orizone.oa.extra.service;

import java.sql.Connection;

public class Transaction
{
 //數(shù)據(jù)庫連接對象
 private Connection connection;
 //事務(wù)次數(shù)
 private int transCount;
 //提交次數(shù)
 private int commitCount;
 //事務(wù)嵌套層次
 private int transDeep;

 int getCommitCount()
 {
  return commitCount;
 }

 void setCommitCount(int commitCount)
 {
  this.commitCount = commitCount;
 }

 Connection getConnection()
 {
  return connection;
 }

 void setConnection(Connection conn)
 {
  this.connection = conn;
 }

 public int getTransCount()
 {
  return transCount;
 }

 void setTransCount(int transCount)
 {
  this.transCount = transCount;
 }

 int getTransDeep()
 {
  return transDeep;
 }

 void setTransDeep(int transDeep)
 {
  this.transDeep = transDeep;
 }
 
 /**
  * 判斷事務(wù)是否完全提交。
  * 通過提交次數(shù)和事務(wù)次數(shù)來判斷事務(wù)是否完全提交。
  * @return
  */
 boolean hasFullExecute()
 {
  return commitCount + 1 == transCount;
 }

}

 

代碼中出現(xiàn)的ConnectionPoolBean是用來負(fù)責(zé)獲取數(shù)據(jù)庫連接的類。整個(gè)思想就是,將一個(gè)Transaction相關(guān)信息(數(shù)據(jù)庫連接對象,事務(wù)次數(shù),提交次數(shù)以及事務(wù)深度)放入到當(dāng)前線程的ThradLocal當(dāng)中,后面的操作都是基于這個(gè)事務(wù)基礎(chǔ)的,這樣才能保證事務(wù)的原子性。在commit的時(shí)候會(huì)判斷當(dāng)前事務(wù)層次深度,如果為頂層,并且提交次數(shù)+1等于事務(wù)次數(shù)(說明事務(wù)是安全完整的執(zhí)行了),才真正提交到數(shù)據(jù)庫。如果不完整,則在endTrnasaction的時(shí)候會(huì)回滾整個(gè)事務(wù)。

雖然這樣能夠?qū)崿F(xiàn)事務(wù)操作,但是無法實(shí)現(xiàn)跨數(shù)據(jù)庫操作,要實(shí)現(xiàn)跨數(shù)據(jù)庫的事務(wù)估計(jì)只能用JTA了。

    本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多