中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

JDBC DAO的設計理念是什么

發布時間:2021-12-22 13:40:27 來源:億速云 閱讀:112 作者:iii 欄目:編程語言

這篇文章主要講解了“JDBC DAO的設計理念是什么”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“JDBC DAO的設計理念是什么”吧!

JDBC DAO中Connection的含義

Connection表示了一個和數據庫的鏈接,底層需要有操作系統的Socket支持,所以Connection是一種資源,既然是一種資源,就需要按照建立,打開,使用,關閉的順序合理的使用。

Connection是Java數據庫操作的基礎,是進行一系列操作的基礎,所有的派生的操作,例如Statement,PreparedStatement,ResultSet等都由Connection直接或者間接的衍生。

如何獲得Connection呢?

方法一,使用DriverManager類來獲取,前提條件是數據庫驅動程序需要在classpath下(即使用數據庫鏈接的程序按照Java的方式可以訪問到)。

Connectionconn=DriverManager.getConnection("jdbc:oracle:thin:@192.168.0.1:1521:ORCL",user,pwd);

方法二,使用數據庫連接池來獲取

什么是數據庫連接池呢,數據庫連接池是標準JavaEE容器的一種服務,例如Webspher,Weblogic,Tomcat等,容器預先建立一些數據庫鏈接,以便應用程序使用的時候從中借取,注意有借有還,當應用程序使用完了之后會將數據庫鏈接還回連接池。(數據源配置請參考其他文檔)

使用連接池的好處是,可以預先建立鏈接,減小在數據庫獲取上的相對時間。

使用連接池獲取數據庫鏈接的方式為:

InitialContextctx=newInitialContext();  DataSourceds=(DataSource)ctx.lookup("java:comp/env/jdbc/DataSource");  Connectionconn=ds.getConnection();

由于在配置數據庫連接池的時候已經定義了URL,用戶名,密碼等信息,所以在程序中使用的時候不需要傳入這些信息。

JDBC DAO中ConnectionManager定義

Connection用來專門管理數據庫鏈接,通常情況下ConnectionManager只有一個方法,調用這個方法將返回一個Connection的實例。通過ConnectionManager可以封裝Connection的獲取方式(例如開發的時候使用DriverManager,運用的時候使用DataSource的方式,但是不需要修改ConnectionManager之外的其他代碼)和追加Connection獲取之前之后的操作(例如針對Connection的屬性的設置)。

下面的代碼是一個ConnectionManager的代碼示例:

packagecom.jpleasure.jdbc.dao;   importjava.sql.Connection;  importjava.sql.DriverManager;  importjava.sql.SQLException;   publicclassConnectionManager{   publicstaticConnectiongetConnection()throwsDaoException{  Connectionconn=null;  try{  conn=DriverManager.getConnection("","","");  }catch(SQLExceptione){  thrownewDaoException("cannotgetdatabaseconnection",e);  }  returnconn;  }  }

如果需要從開發模式變為運用模式,只需要將上述代碼修改為:

packagecom.jpleasure.jdbc.dao;   importjava.sql.Connection;  importjava.sql.DriverManager;  importjava.sql.SQLException;   publicclassConnectionManager{   publicstaticConnectiongetConnection()throwsDaoException{  Connectionconn=null;  try{  Contextctx=newInitialContext();  DataSourceds=(DataSource)ctx.lookup("jdbc/dsname");  conn=ds.getConnection();  }catch(NamingExceptione){  thrownewDaoException("cannotfinddatasource",e);  }catch(SQLExceptione){  thrownewDaoException("cannotgetdatabaseconnection",e);  }  returnconn;  }  }   如果需要預先設定Connection的一些屬性,也可以在上述代碼中設定,例如:  packagecom.jpleasure.jdbc.dao;   importjava.sql.Connection;  importjava.sql.DriverManager;  importjava.sql.SQLException;   publicclassConnectionManager{   publicstaticConnectiongetConnection()throwsDaoException{  Connectionconn=null;  try{  Contextctx=newInitialContext();  DataSourceds=(DataSource)ctx.lookup("jdbc/dsname");  conn=ds.getConnection();  conn.setAutoCommit(false);  }catch(NamingExceptione){  thrownewDaoException("cannotfinddatasource",e);  }catch(SQLExceptione){  thrownewDaoException("cannotgetdatabaseconnection",e);  }  returnconn;  }  }   CommonDao定義  屬性和構造方法  通常情況下,CommonDao要有一個Connection的引用。所有一個CommonDao的實例的所有方法的調用都需要依賴于這個Connection。需要一個Connection的另外一個原因是如果各個方法需要保證在一個事務環境中(上下文中),必須保證所有的操作都在一個Connection上。  構造方法通常需要將類型為Connection的屬性實例化,例如:   packagecom.jpleasure.jdbc.dao;   importjava.sql.Connection;   publicclassCommonDao{   privateConnectionconn;   publicCommonDao()throwsDaoException{  this.conn=ConnectionManager.getConnection();  }  }

事務方法

begin()

開始一個事務,調用CommonDao的begin方法之后,所以的后續操作將會在一個事務環境內,要么全部提交,要么全部回滾。

commit()

提交一個事務,必須在begin調用之后調用。且和rollback方法互斥。

rollback()

回滾一個事務,必須在begin方法調用之后調用。且和commit方法互斥。

事務的實現有兩種方法,一種是使用基于單一Connection的事務,另外一種方法是使用容器的JTA(JavaTransactionAPI)。需要注意的是***種方法可以在任何環境下使用,但是只能是針對單一的數據庫鏈接。第二種方法智能在支持JTA的JavaEE容器中使用(例如Websphere,Weblogic等,Tomcat默認不支持),但是支持多個Connection實例。

***種方法代碼為:

packagecom.jpleasure.jdbc.dao;   importjava.sql.Connection;  importjava.sql.SQLException;   publicclassCommonDao{   privateConnectionconn;   publicCommonDao()throwsDaoException{  this.conn=ConnectionManager.getConnection();  }   publicvoidbegin()throwsDaoException{  if(conn!=null){  try{  conn.setAutoCommit(false);  }catch(SQLExceptione){  thrownewDaoException("cannotbegintransaction",e);  }  }else{  thrownewDaoException("connectionnotopened!");  }  }   publicvoidcommit()throwsDaoException{  try{  if(conn!=null&&!conn.getAutoCommit()){  conn.commit();  conn.setAutoCommit(true);  }else{  if(conn==null){  thrownewDaoException("connectionnotopened!");  }else{  thrownewDaoException("firstbeginthencommitplease!");  }  }  }catch(SQLExceptione){  thrownewDaoException("cannotcommittransaction!",e);  }  }   publicvoidrollback()throwsDaoException{  try{  if(conn!=null&&!conn.getAutoCommit()){  conn.rollback();  conn.setAutoCommit(true);  }else{  if(conn==null){  thrownewDaoException("connectionnotopened!");  }else{  thrownewDaoException("firstbeginthenrollbackplease!");  }  }  }catch(SQLExceptione){  thrownewDaoException("cannotrollbacktransaction!",e);  }  }  }

第二種我們在使用DAO的實例中介紹如何使用(@TODO)

新建兩個DAO,做不同的操作,使用JTA保證事務完整。

查詢方法

查詢方法也許是CommonDao最常用的方法,查詢方法需要將數據庫的結果返回給畫面。返回值我們一般不使用ResultSet,因為ResultSet依賴于Connection,如果Connection關閉,ResultSet將不再有效,所以我們通常將ResultSet轉變為一個List之后返回。

在說明查詢方法之前,我們先說說如何將數據庫中的內容放在List中,我們使用一個List表示一個查詢結果集合,使用一個Map表示集合中的一行,Map的key表示數據庫表的字段名字,Value表示數據庫字段的內容。代碼為:

privateListconvert(ResultSetrs)throwsDaoException{   //recordlist  ListretList=newArrayList();   try{  ResultSetMetaDatameta=rs.getMetaData();   //columncount  intcolCount=meta.getColumnCount();   //eachrecord  while(rs.next()){   MaprecordMap=newHashMap();   //eachcolumn  for(inti=1;i<=colCount;i++){  //columnname  Stringname=meta.getColumnName(i);  //columnvalue  Objectvalue=rs.getObject(i);  //addcolumntorecord  recordMap.put(name,value);  }  //adrecordtolist  retList.add(recordMap);  }  }catch(SQLExceptionex){  thrownewDaoException("cannotconvertresultsettolistofmap",ex);  }  returnretList;  }

為了避免Sql注入的安全問題,我們通常使用PreparedStatement,在使用PreparedStatement的時候涉及到如何將傳入參數設置到PreparedStatement上面,參看以下的共通方法:

privatevoidapply(PreparedStatementpstmt,Listparams)throwsDaoException{  try{  //ifparamsexist  if(params!=null&&para;ms.size()>0){  //parametersiterator  Iteratorit=params.iterator();   //parameterindex  intindex=1;  while(it.hasNext()){   Objectobj=it.next();  //ifnullset""  if(obj==null){  pstmt.setObject(index,"");  }else{  //elsesetobject  pstmt.setObject(index,obj);  }   //nextindex  index++;  }  }  }catch(SQLExceptionex){  thrownewDaoException("cannotapplyparameter",ex);  }  }   接著我們繼續說我們的查詢方法,有了上述兩個方法,我們的查詢方法就非常簡單了:  publicListquery(Stringsql,Listparams)throwsDaoException{  Listresult=null;  PreparedStatementpstmt=null;  ResultSetrs=null;  try{  pstmt=conn.prepareStatement(sql);  this.apply(pstmt,params);  rs=pstmt.executeQuery();  result=this.convert(rs);  }catch(SQLExceptionex){  thrownewDaoException("cannotexecutequery",ex);  }finally{  if(rs!=null){  try{  rs.close();  }catch(SQLExceptione){  //nothing  }  }  if(pstmt!=null){  try{  pstmt.close();  }catch(SQLExceptione){  //nothing  }  }  }  returnresult;  }

特殊的查詢方法(返回單值)

有時候為了方便使用,我們需要返回單值的產尋方法,例如selectmax(id)fromtable_a,selectcount(id)fromtable_b等。以下的代碼使用了上述通用的查詢方法,代碼為:

publicObjectqueryOne(Stringsql,Listparams)throwsDaoException{  Listlist=this.query(sql,params);   if(list==null||list.size()==0){  thrownewDaoException("datanotexist");  }else{  Maprecord=(Map)list.get(0);  if(record==null||record.size()==0){  thrownewDaoException("datanotexist");  }else{  returnrecord.values().toArray()[0];  }  }  }

更新,刪除,插入方法

由于在JDBC中這三個方法都是用了一個execute完成,所以這里我們也使用一個方法來完成這些功能。代碼為:

publicintexecute(Stringsql,Listparams)throwsDaoException{  intret=0;  PreparedStatementpstmt=null;  try{  pstmt=conn.prepareStatement(sql);  this.apply(pstmt,params);  ret=pstmt.executeUpdate();  }catch(SQLExceptionex){  thrownewDaoException("",ex);  }finally{  if(pstmt!=null){  try{  pstmt.close();  }catch(SQLExceptione){  //nothing.  }  }  }   returnret;  }

批處理方法(查詢)

有些時候為了便于操作,需要一次查詢多條SQL語句,我們稱之為批處理,實現參看以下方法,其中為了和query方法做區分,將參數和返回值都改為了數組形式。

publicList[]queryBatch(String[]sqlArray,List[]paramArray)throwsDaoException{  Listrets=newArrayList();  if(sqlArray.length!=paramArray.length){  thrownewDaoException("sqlsizenotequalparametersize");  }else{  for(inti=0;iStringsql=sqlArray[i];  Listparam=paramArray[i];  Listret=this.query(sql,param);  rets.add(ret);  }  return(List[])rets.toArray();  }  }

批處理方法(更新)

有些時候需要一次更新多條Sql語句,為了便于操作,添加了批處理更新操作,參看以下代碼,為了和更新方法區分,將參數和返回值都改為了數組形式。

publicint[]executeBatch(String[]sqlArray,List[]paramArray)throwsDaoException{  Listrets=newArrayList();  if(sqlArray.length!=paramArray.length){  thrownewDaoException("sqlsizenotequalparametersize");  }else{  for(inti=0;iintret=this.execute(sqlArray[i],paramArray[i]);  rets.add(newInteger(ret));  }   int[]retArray=newint[rets.size()];  for(inti=0;iretArray[i]=((Integer)rets.get(i)).intValue();  }   returnretArray;  }  }

資源釋放

由于CommonDao有一個Connection的屬性,且Connection屬于稀缺資源,所以在CommonDao不需要在使用的時候需要顯示的關閉Connection。代碼如下:

publicvoidclose()throwsDaoException{  try{  if(conn!=null&&conn.getAutoCommit()){  conn.close();  }else{  if(conn==null){  thrownewDaoException("cannotclosenullconnection,firstnewthenclose");  }else{  thrownewDaoException("transactionisrunning,rollbakcorcommitbeforcloseplease.");  }  }  }catch(SQLExceptionex){  thrownewDaoException("Cannotclosecommondao");  }  }

JDBC工具類(JDBCUtilClass)

在上述的代碼中我們看到有很多的無用的處理,例如:

if(pstmt!=null){  try{  pstmt.close();  }catch(SQLExceptione){  //nothing.  }  }

為什么要有這些處理呢?說先這些處理發生的位置都是在正常處理完成之后,這些處理(例如pstmt.close())即使失敗也沒有影響,這個時候我們需要做上述的無用處理,這正是JDBCAPI的一個小小的瑕疵。我們通常使用一個特殊的靜態工具來來做補充,例如:

packagecom.jpleasure.jdbc.dao;   importjava.sql.Connection;  importjava.sql.PreparedStatement;  importjava.sql.ResultSet;  importjava.sql.SQLException;   publicclassJDBCUtil{  publicvoidsafelyClose(Connectionconn){  if(conn!=null){  try{  conn.close();  }catch(SQLExceptione){  //  }  }  }  publicvoidsafelyClose(PreparedStatementpstmt){  if(pstmt!=null){  try{  pstmt.close();  }catch(SQLExceptione){  //  }  }  }  publicvoidsafelyClose(ResultSetrs){  if(rs!=null){  try{  rs.close();  }catch(SQLExceptione){  //  }  }  }  }

JDBC DAO中異常處理

也許細心的你已經發現了一個問題,為什么所有拋出異常的地方我們都是將SQLException包裝在了DaoException之內拋出呢,為什么不直接拋出SQLException呢?有兩個原因,***,可以細化,分類Exception拋出合適的異常,添加合適的消息,第二,隔離和Dao和業務邏輯的耦合,可以方便的修改Dao層而不會影響到業務邏輯層。另外需要注意,DaoExcetion中可以包含SQLException,這個時候可以為客戶提供更詳細的錯誤信息,例如ORA-12524等內容,但是很少見到。

packagecom.jpleasure.jdbc.dao;  publicclassDaoExceptionextendsException{  publicDaoException(){  super();  }  publicDaoException(Stringmessage,Throwablecause){  super(message,cause);  }  publicDaoException(Stringmessage){  super(message);  }  publicDaoException(Throwablecause){  super(cause);  }  }

感謝各位的閱讀,以上就是“JDBC DAO的設計理念是什么”的內容了,經過本文的學習后,相信大家對JDBC DAO的設計理念是什么這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

樟树市| 泸西县| 通州市| 赤城县| 自贡市| 辰溪县| 兰州市| 阳东县| 临沂市| 南京市| 乐清市| 崇文区| 沐川县| 甘孜县| 桐乡市| 读书| 麻栗坡县| 平乡县| 社旗县| 平罗县| 登封市| 台山市| 桃园市| 延吉市| 沈丘县| 皮山县| 永清县| 罗山县| 仲巴县| 布尔津县| 称多县| 温宿县| 娄烦县| 克拉玛依市| 莆田市| 广平县| 明光市| 栾城县| 平凉市| 苍梧县| 三河市|