程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 客串java開發:數據庫訪問的流程簡化

客串java開發:數據庫訪問的流程簡化

編輯:關於JAVA

如果非 .net 相關技術不適宜發表在園子的首頁,請告知我撤下該主題!

我從事 asp/.net 開發有兩年多了,其間還做過很多 winform 或 windows console 程序,這些只是表現形式;相關技術 ado.net,多線程,.net remoting 等等或多或少有所應用或研究。剛開始工作因為生活、興趣,現在發展為一種人生哲學:試圖在創造中找到生命存在的意義。難道果真如“許三多”說的:好好活就是做有意義的事,做有意義的事就是好好活?

閒話少扯。最近有幸接觸 java,早前我因受 .net 蠱惑,總把她當做異類,印象中這種語言工具書寫繁瑣、配置雜亂,讓人無暇全身心關注業務邏輯,因此,除了對其本身諸多麻煩的恐懼,還有一種詭異的不屑。幾個月前“邂逅”老牌艷星 c++,方知世間騷字怎解,悔恨帶著有色眼鏡看待開源。

java 還算是個很簡便的語言工具(我都不知道該把她當成一個語言,還是一個工具,看官們仁者見仁吧)。記得大學期間應用 jsp 搞過一個《醫院管理系統》,當時建個小網站,鏈接數據庫做點小操作,無不令人抓狂,現在看來,無非是當時的我們心高氣傲,以為用 vs2003 拖個玩意點擊“下一步”就顯得很牛逼。自然,語言以及開發工具的易用程度上,java 干不過 .net,但從功能以及成本而言,後者還是很有優勢的,風行那麼多年的 j2ee,還是擁有相當的高端市場。

曾經我寫過一篇隨筆,談到 .net 環境下“如何簡化數據庫的訪問操作”(http://www.cnblogs.com/howard-queen/archive/2009/07/14/1523500.html),今天我很驚詫,原來 java 也完全可以實現。通常,java 進行數據操作也是通過三個類 Connection(IDbConnection),Statement(IDbCommand),ResultSet(IDataReader),我將長期以來總結出的數據操作接口實現了一個不含參數的簡化 java 版本(請同學們同時注意 java 與 c# 不同的命名規范):

package queen.data;
/*
  * 統一數據訪問接口
  *
  * @author Howard Queen
  * @version 1.0.1, 2010/10/12
  * */
public interface IExecutor {
   String getConnectionString();
   void setConnectionString(String value) throws Exception;
   int getTimeout();
   void setTimeout(int value);
   /*
    * 執行語句獲取數據集
    * */
   QueryResult executeQuery(String statement) throws Exception;
   /*
    * 執行語句獲取單個數據
    * */
   Object executeScale(String statement) throws Exception;
   /*
    * 執行語句獲取影響的行數或其他。
    * */
   int executeNonQuery(String statement) throws Exception;
}

為了便於在獲取數據後集中釋放非托管資源,我使用自定義的 QueryResult 類返回查詢結果,而不是官方 ResultSet 。該類主要提供 close() 方法,其定義如下:

package queen.data;

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

/*
  * 數據返回類,便於集中釋放相關非托管資源。
  *
  * @author Howard Queen
  * @version 1.0.1, 2010/10/13 
  * */
public final class QueryResult {

   private Connection _connection;
   private Statement _statement;
   private ResultSet _resultSet;

   public QueryResult(Connection connection, Statement statement, ResultSet resultSet){
     _connection = connection;
     _statement = statement;
     _resultSet = resultSet;
   }

   private Connection getConnection(){
     return _connection;
   }

   private Statement getStatement(){
     return _statement;
   }

   public ResultSet getResultSet(){
     return _resultSet;
   }

   public void close() throws SQLException{
     getResultSet().close();
     getStatement().close();
     getConnection().close();
   }

}

同時,實現一個鏈接傳統數據庫的輔助類:

package queen.data;

import java.io.IOException;
import java.sql.Connection;
import java.sql.Statement;
import java.sql.ResultSet;
import java.sql.DriverManager;
import java.util.Properties;

/*
  * 數據庫訪問器
  *
  * @author Howard Queen
  * @version 1.0.1, 2010/10/12
  * */
public final class DbExecutor implements IExecutor {

   static{
     try {
       Class.forName("com.mysql.jdbc.Driver");
     } catch (ClassNotFoundException e) {
       e.printStackTrace();
     }
   }

   private String _connectionString;
   private String _userName, _password;
   public String getConnectionString() {
     return _connectionString;
   }
   public void setConnectionString(String value) throws Exception {
     throw new Exception("請使用同名重載方法 setConnectionString(String connectionString,

                  String userName, String password) 設置鏈接參數!");
   }

   public void setConnection(String connectionString, String userName, String password){
     _connectionString = connectionString;
     _userName = userName;
     _password = password;
   }

   public void setConnectionFromProperties(String fileName, String connectionStringPropertyName,

         String userNamePropertyName, String passwordPropertyName) throws IOException{
     Properties p = new Properties();
     p.load(DbExecutor.class.getResourceAsStream(fileName));
     String connectionString = p.getProperty(connectionStringPropertyName);
     String userName = p.getProperty(userNamePropertyName);
     String password = p.getProperty(passwordPropertyName);
     setConnection(connectionString, userName, password);
   }

   public String getUserName(){
     return _userName;
   }

   public String getPassword(){
     return _password;
   }

   private int _timeout;
   public int getTimeout() {
     return _timeout;
   }
   public void setTimeout(int value) {
     _timeout = value;
   }

   public int executeNonQuery(String statement) throws Exception{
     Connection con = null;
     Statement stm = null;
     try{
       con = DriverManager.getConnection(getConnectionString(), getUserName(), getPassword());
       stm = con.createStatement();
       return stm.executeUpdate(statement);
     }
     catch(Exception E){
       throw E;
     }
     finally{
       if(stm != null){
         stm.close();
       }
       if(con != null){
         con.close();
       }
     }
   }

   public QueryResult executeQuery(String statement) throws Exception {
     Connection con = DriverManager.getConnection(getConnectionString(), getUserName(), getPassword());
     Statement stm = con.createStatement();
     return new QueryResult(con, stm, stm.executeQuery(statement));
   }

   public Object executeScale(String statement) throws Exception {
     Connection con = null;
     Statement stm = null;
     ResultSet rs = null;
     try{
       con = DriverManager.getConnection(getConnectionString(), getUserName(), getPassword());
       stm = con.createStatement();
       rs = stm.executeQuery(statement);
       if(rs.next()){
         return rs.getObject(0);
       }
       return null;
     }
     catch(Exception E){
       throw E;
     }
     finally{
       if(rs != null){
         rs.close();
       }
       if(stm != null){
         stm.close();
       }
       if(con != null){
         con.close();
       }
     }
   }

}

這樣一來,從前進行數據庫操作繁瑣的構造 Connection、Statement 以及 ResultSet 等均可以省略了。例子如下:

public static void main(String[] args) throws Exception {
     DbExecutor b = new DbExecutor();
     b.setConnection("jdbc:mysql://databaseUrl:3306/dbName?useUnicode=true&characterEncoding=utf8",
         "myusername", "mypassword");
     QueryResult r = b.executeQuery("SELECT Name FROM Users LIMIT 10");
     ResultSet s = r.getResultSet();
     while(s.next()){
       System.out.println(s.getString(1));
     }
     r.close();//需要手動釋放

     int maxUseAge = b.executeScale("SELECT MAX(Age) FROM Users");//自動釋放 
   }

考慮到一般數據庫連接參數保存在配置文件中,DbExecutor 還特別提供從配置文件加載鏈接參數的方法:

public void setConnectionFromProperties(String fileName, String connectionStringPropertyName,

         String userNamePropertyName, String passwordPropertyName) throws IOException{...}

哎,實在不知道該做點什麼有意義的事,只好這樣弄點殘羹冷炙邀各位閒雜人等一起賞日(今天上海還是個陰天,日只出現了不到半小時)。但拋磚是為引玉,我知道園子裡臥著華南虎、藏著史前龍,我所刻意追求的優雅編碼,在很多東方求敗看來不過是個兒戲;你們很多人身懷葵花寶典,卻少有傳閱,哎,斬不斷的技術迷信,遲早要害得小年輕們色老顏衰,青春從此一日不復返!

呵呵,碰了 java,人說話都糊裡糊塗了,哈哈。兄弟們要守住這份貞操啊!

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved