顯示具有 資料庫 標籤的文章。 顯示所有文章
顯示具有 資料庫 標籤的文章。 顯示所有文章

[MS-SQL]不具自動容錯移轉的鏡像設定

以下的資料庫鏡像架構大致上就是

應用程式==data==>主體伺服器==data==>鏡像伺服器

環境

兩台一樣環境的伺服器

  • Windows Server 2003 R2
  • Microsoft SQL Server 2008 R2
  • Microsoft SQL Server Management Studio 10.0.1600.22

SQL Server服務啟動帳號設定

  1. 在windows服務(services.msc) 列表中,找到SQL Server,右鍵選內容或雙擊
  2. 後選擇登入頁,在此帳戶中這裡配置登錄用戶和密碼,這個地方建議兩台伺服器都配置一組一樣的帳號,並將此帳戶加到SQL Server的管理帳戶,後續的鏡像會用這組帳號繼續設定
  3. SQL Server Agent 啟動帳號也一樣設置

主體伺服器備份

  1. 在主體伺服器用windows帳戶登入Management Studio工具,這個動作是為了後續使用語法產生SQL檔時才不會有權限錯誤
  2. 產生資料庫建立語法
    以物件總管詳細資料選取需要鏡像的資料庫,並產生Create語法(選檔案即可產生.sql檔)
  3. 匯出每個資料庫的備份檔
    backup database [DataBaseName1] to disk='D:\dbbackup\[DataBaseName1].bak'  with init
    GO
    backup database [DataBaseName2] to disk='D:\dbbackup\[DataBaseName2].bak' with init
    GO
  4. 匯出每個資料庫的記錄檔
    BACKUP LOG [DataBaseName1] TO DISK = 'D:\dbbackup\[DataBaseName1].log'
    GO
    BACKUP LOG [DataBaseName2] TO DISK = 'D:\dbbackup\[DataBaseName2].log'
    GO

還原資料到鏡像伺服器

  1. 將上一步驟產生的檔案(含*.sql、*.bak、*.log)所在dbbackup資料夾複製到鏡像資料庫
  2. 在鏡像伺服器用windows帳戶登入Management Studio工具
  3. 建立資料庫:以Management Studio開啟建立資料庫用的sql檔並執行,即可產生與主體伺服器相同名稱的資料庫
  4. 還原資料
    restore database [DataBaseName1] from disk='D:\backupz\[DataBaseName1].bak' with replace,norecovery
    GO
    restore database [DataBaseName2] from disk='D:\backupz\[DataBaseName2].bak' with replace,norecovery
    GO
  5. 還原記錄檔
    RESTORE LOG [DataBaseName1] FROM DISK = 'D:\backupz\[DataBaseName1].log'  WITH FILE=1, NORECOVERY
    GO
    RESTORE LOG [DataBaseName2] FROM DISK = 'D:\backupz\[DataBaseName2].log' WITH FILE=1, NORECOVERY
    GO
  6. 成功後會看到建立起來的資料庫名稱後面會出現(正在還原...)的狀態

於主體伺服器啟動鏡像服務

  1. 在主體伺服器的資料庫上點右鍵,選屬性,並選擇[鏡像]頁籤。接著點選[設定安全性]鈕就會開啟[設定資料庫鏡像安全性精靈]

  2. 於見證伺服器選擇頁選擇否,不使用見證伺服器

  3. 第一次使用鏡像設定會選擇本機的鏡像服務Port與鏡像端點名稱,此處採用預設值即可

  4. 設定鏡像伺服器的連線資訊

  5. 服務帳戶不用設定

  6. 完成後就會進行設定,第一次設定時會自動產生服務端點,這時就會啟動服務的Port

  7. 完成後會詢問是否要啟動鏡像,選擇不要啟動鏡像。這時如果直接啟動如果連線網域名稱錯誤就會失敗(而且還不給設定…)

  8. 接著就可以在伺服器網路位址確認鏡像伺服器的連線資訊

    需注意的是他有個奇怪的驗證,就是預設他會把鏡像伺服器的電腦名稱帶到鏡像的位址,但他的預設格式是[電腦名稱.網域名稱],沒有網域名稱時就必須在電腦名稱後面加一個句點.,否則你就會看到下面的錯誤

  9. 啟動成功後如下圖

  10. 重覆此上述動作把所有資料庫的鏡像都啟動

[C#]MS-SQL資料庫存取函式

序言

我將C#存取MS-SQL的程式包了一層方便使用。

環境

  • VS2008
  • MS-SQL 2008

存取函式類別

using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Text;
using System.Data;

namespace MyCommon.DAO
{

    /// 
    /// MS-SQL連線物件
    /// 
    public class MSSQLBaseIO
    {
        SqlConnection sqlConn = null;
        /// 
        /// 建立連線物件
        /// 
        /// 連線字串,如Data Source=localhost;Initial Catalog=dbName;User id=Account;Password=Password;
        public MSSQLBaseIO(string connectionString)
        {
            sqlConn = new SqlConnection(connectionString);
        }
        /// 
        /// 建立連線物件
        /// 
        /// 可為localhost / domainname  / 或 IP
        /// 若Host為IP,則需為true
        /// 不設定則填0,則會用MSSQL預設port
        /// 不設定則填null,express版預設為SQLEXPRESS,正式版預設為MSSQLSERVER,從服務組態可以看到
        /// 資料庫名稱
        /// 是否使用 Windows 整合驗証方式連線,false則必需填帳號密碼
        /// 登入帳號
        /// 登入密碼
        /// 連線逾期,不設定則填0
        public MSSQLBaseIO(string host,bool isHostIP,int port,
            string instanceName, string dbName,
            bool isIntegratedSecurity,
            string id, string password,
            int timeout)
        {
            StringBuilder connectionString = new StringBuilder();
            if (isHostIP) connectionString.Append("Data Source=tcp:" + host);
            else connectionString.Append("Data Source=" + host);
            if (instanceName != null) connectionString.Append("\\" + instanceName);
            if (port != 0) connectionString.Append("," + port);
            connectionString.Append(";");
            connectionString.Append("Initial Catalog=" + dbName + ";");
            if (isIntegratedSecurity) connectionString.Append("integrated security=true;");
            if (id!=null) connectionString.Append("User id=" + id + ";");
            if (password!=null) connectionString.Append("Password=" + password + ";");
            if (timeout>0) connectionString.Append("Connect Timeout=" + timeout + ";");
            sqlConn = new SqlConnection(connectionString.ToString());
        }
        /// 
        /// 取得目前連線物件
        /// 
        /// 
        public SqlConnection getConnection()
        {
            return sqlConn;
        }

        Exception _exception = null;
        /// 
        /// 取得上次執行後的錯誤
        /// 
        /// 
        public Exception getException(){
            return _exception;
        }
        /// 
        /// 關閉連線
        /// 
        public void closeConn()
        {
            closeConn(true);
        }
        /// 
        /// 關閉連線
        /// 
        /// 是否關閉連線
        public void closeConn(bool isCloseConn){
            if (sqlConn != null && isCloseConn && sqlConn.State!=System.Data.ConnectionState.Closed)
            {
                sqlConn.Close();
            }
        }
        /// 
        /// 取得新的Transaction物件
        /// 
        /// Transaction物件
        public SqlTransaction getNewTransaction()
        {
            if (sqlConn.State != System.Data.ConnectionState.Open)
                sqlConn.Open();
            return sqlConn.BeginTransaction();
        }

        /// 
        /// 執行SQL命令,執行後會關閉SQL連線
        /// 
        /// SQL命令
        /// 是否為預存程序
        /// 變動筆數
        public int ExecuteNonQuery(string sqlcmd, bool isStoredProcedure)
        {
            return ExecuteNonQuery(sqlcmd,isStoredProcedure, true);
        }
        /// 
        /// 執行SQL命令
        /// 
        /// SQL命令
        /// 是否為預存程序
        /// 是否關閉連線
        /// 變動筆數
        public int ExecuteNonQuery(string sqlcmd, bool isStoredProcedure, bool isCloseConn)
        {
            SqlParameter[] sqlparams = null;
            return ExecuteNonQuery(sqlcmd, ref sqlparams, isStoredProcedure, isCloseConn);
        }
        /// 
        /// 執行SQL命令
        /// 
        /// SQL命令
        /// 命令參數,可為null,參數名稱為 @參數名稱
        /// 是否為預存程序
        /// 是否關閉連線
        /// 變動筆數
        public int ExecuteNonQuery(string sqlcmd, ref SqlParameter[] sqlparams, bool isStoredProcedure, bool isCloseConn)
        {
            return ExecuteNonQuery(sqlcmd, ref sqlparams, isStoredProcedure, null, isCloseConn);
        }
        /// 
        /// 執行SQL命令
        /// 
        /// SQL命令
        /// 命令參數,可為null,參數名稱為 @參數名稱
        /// 是否為預存程序
        /// SqlTransaction,可為null
        /// 是否關閉連線
        /// 變動筆數
        public int ExecuteNonQuery(string sqlcmd, ref SqlParameter[] sqlparams,bool isStoredProcedure, SqlTransaction trans, bool isCloseConn)
        {
            int result = -1;
            _exception = null;
            try
            {
                if (sqlConn.State != System.Data.ConnectionState.Open)
                    sqlConn.Open();
                SqlCommand cmd;
                if (trans==null)
                    cmd = new SqlCommand(sqlcmd, sqlConn);
                else
                    cmd = new SqlCommand(sqlcmd, sqlConn, trans);
                if(isStoredProcedure)
                    cmd.CommandType = CommandType.StoredProcedure;
                if (sqlparams!=null)
                    cmd.Parameters.AddRange(sqlparams);
                result = cmd.ExecuteNonQuery();
            }
            catch (Exception ex)
            {
                _exception = ex;
            }
            finally
            {
                closeConn(isCloseConn);
            }
            return result;
        }
        /// 
        /// 取得多列資料,執行後會關閉SQL連線
        /// 
        /// SQL命令
        /// 是否為預存程序
        /// 是否關閉連線
        /// 多列資料
        public List ExecuteReader(string sqlcmd, bool isStoredProcedure)
        {
            return ExecuteReader(sqlcmd, isStoredProcedure, true);
        }
        /// 
        /// 取得多列資料
        /// 
        /// SQL命令
        /// 是否為預存程序
        /// 是否關閉連線
        /// 多列資料
        public List ExecuteReader(string sqlcmd, bool isStoredProcedure, bool isCloseConn)
        {
            SqlParameter[] sqlparams = null;
            return ExecuteReader(sqlcmd, ref sqlparams, isStoredProcedure, isCloseConn);
        }
        /// 
        /// 取得多列資料
        /// 
        /// SQL命令
        /// 命令參數,可為null,參數名稱為 @參數名稱
        /// 是否為預存程序
        /// 是否關閉連線
        /// 多列資料
        public List ExecuteReader(string sqlcmd, ref SqlParameter[] sqlparams, bool isStoredProcedure, bool isCloseConn)
        {
            return ExecuteReader(sqlcmd, ref sqlparams, isStoredProcedure, null, isCloseConn);
        }
        /// 
        /// 取得多列資料
        /// 
        /// SQL命令
        /// 命令參數,可為null,參數名稱為 @參數名稱
        /// 是否為預存程序
        /// SqlTransaction,可為null
        /// 是否關閉連線
        /// 多列資料
        public List ExecuteReader(string sqlcmd, ref SqlParameter[] sqlparams, bool isStoredProcedure, SqlTransaction trans, bool isCloseConn)
        {
            List result = null;
            _exception = null;
            SqlDataReader reader = null;
            try
            {
                if (sqlConn.State != System.Data.ConnectionState.Open)
                    sqlConn.Open();
                SqlCommand cmd;
                if (trans == null)
                    cmd = new SqlCommand(sqlcmd, sqlConn);
                else
                    cmd = new SqlCommand(sqlcmd, sqlConn, trans);
                if (isStoredProcedure)
                    cmd.CommandType = CommandType.StoredProcedure;
                if (sqlparams != null)
                    cmd.Parameters.AddRange(sqlparams);
                reader = cmd.ExecuteReader();
                object[] item;
                if (reader.HasRows)
                {
                    result = new List();
                    while (reader.Read())
                    {
                        item = new object[reader.FieldCount];
                        for (int j = 0; j < reader.FieldCount; j++)
                        {
                            item[j] = reader[j];
                        }
                        result.Add(item);
                    }
                }
            }
            catch (Exception ex)
            {
                _exception = ex;
            }
            finally
            {
                if (reader!=null) reader.Close();
                closeConn(isCloseConn);
            }
            return result;
        }

        /// 
        /// 取得單一值,執行後會關閉SQL連線
        /// 
        /// SQL命令
        /// 是否為預存程序
        /// 單一值
        public object ExecuteScalar(string sqlcmd, bool isStoredProcedure)
        {
            return ExecuteScalar(sqlcmd, isStoredProcedure, true);
        }
        /// 
        /// 取得單一值
        /// 
        /// SQL命令
        /// 是否為預存程序
        /// 是否關閉連線
        /// 單一值
        public object ExecuteScalar(string sqlcmd, bool isStoredProcedure, bool isCloseConn)
        {
            SqlParameter[] sqlparams = null;
            return ExecuteScalar(sqlcmd, ref sqlparams, isStoredProcedure, isCloseConn);
        }
        /// 
        /// 取得單一值
        /// 
        /// SQL命令
        /// 命令參數,可為null,參數名稱為 @參數名稱
        /// 是否為預存程序
        /// 是否關閉連線
        /// 單一值
        public object ExecuteScalar(string sqlcmd,ref SqlParameter[] sqlparams, bool isStoredProcedure, bool isCloseConn)
        {
            return ExecuteScalar(sqlcmd,ref sqlparams, isStoredProcedure, null, isCloseConn);
        }
        /// 
        /// 取得單一值
        /// 
        /// SQL命令
        /// 命令參數,可為null,參數名稱為 @參數名稱
        /// 是否為預存程序
        /// SqlTransaction,可為null
        /// 是否關閉連線
        /// 單一值
        public object ExecuteScalar(string sqlcmd,ref SqlParameter[] sqlparams, bool isStoredProcedure, SqlTransaction trans, bool isCloseConn)
        {
            object result = null;
            _exception = null;
            try
            {
                if (sqlConn.State != System.Data.ConnectionState.Open)
                    sqlConn.Open();
                SqlCommand cmd;
                if (trans == null)
                    cmd = new SqlCommand(sqlcmd, sqlConn);
                else
                    cmd = new SqlCommand(sqlcmd, sqlConn, trans);
                if (isStoredProcedure)
                    cmd.CommandType = CommandType.StoredProcedure;
                if (sqlparams != null)
                    cmd.Parameters.AddRange(sqlparams);
                result = cmd.ExecuteScalar();
              
            }
            catch (Exception ex)
            {
                _exception = ex;
            }
            finally
            {
                closeConn(isCloseConn);
            }
            return result;
        }

        /// 
        /// 取得單一列資料,執行後會關閉SQL連線
        /// 
        /// SQL命令
        /// 是否為預存程序
        /// 單一列資料
        public object[] ExecuteReaderSingleRow(string sqlcmd, bool isStoredProcedure)
        {
            return ExecuteReaderSingleRow(sqlcmd, isStoredProcedure, true);
        }
        /// 
        /// 取得單一列資料
        /// 
        /// SQL命令
        /// 是否為預存程序
        /// 是否關閉連線
        /// 單一列資料
        public object[] ExecuteReaderSingleRow(string sqlcmd, bool isStoredProcedure, bool isCloseConn)
        {
            SqlParameter[] sqlparams = null;
            return ExecuteReaderSingleRow(sqlcmd, ref sqlparams, isStoredProcedure, isCloseConn);
        }
        /// 
        /// 取得單一列資料
        /// 
        /// SQL命令,參數部份以 @參數名稱 標示
        /// 命令參數,可為null,參數名稱為 @參數名稱
        /// 是否為預存程序
        /// 是否關閉連線
        /// 單一列資料
        public object[] ExecuteReaderSingleRow(string sqlcmd,ref SqlParameter[] sqlparams, bool isStoredProcedure, bool isCloseConn)
        {
            return ExecuteReaderSingleRow(sqlcmd,ref sqlparams, isStoredProcedure, null, isCloseConn);
        }
        /// 
        /// 取得單一列資料
        /// 
        /// SQL命令,參數部份以 @參數名稱 標示
        /// 命令參數,可為null,參數名稱為 @參數名稱
        /// 是否為預存程序
        /// SqlTransaction,可為null
        /// 是否關閉連線
        /// 單一列資料
        public object[] ExecuteReaderSingleRow(string sqlcmd, ref SqlParameter[] sqlparams, bool isStoredProcedure, SqlTransaction trans, bool isCloseConn)
        {
            object[] result = null;
            _exception = null;
            SqlDataReader reader = null;
            try
            {
                if (sqlConn.State != System.Data.ConnectionState.Open)
                    sqlConn.Open();
                SqlCommand cmd;
                if (trans == null)
                    cmd = new SqlCommand(sqlcmd, sqlConn);
                else
                    cmd = new SqlCommand(sqlcmd, sqlConn, trans);
                if (isStoredProcedure)
                    cmd.CommandType = CommandType.StoredProcedure;
                if (sqlparams != null)
                    cmd.Parameters.AddRange(sqlparams);
                reader = cmd.ExecuteReader(CommandBehavior.SingleRow);
                object[] item;
                if (reader.HasRows)
                {
                    reader.Read();
                    item = new object[reader.FieldCount];
                    for (int j = 0; j < reader.FieldCount; j++)
                    {
                        item[j] = reader[j];
                    }
                    result = item;
                }
            }
            catch (Exception ex)
            {
                _exception = ex;
            }
            finally
            {
                if (reader != null) reader.Close();
                closeConn(isCloseConn);
            }
            return result;
        }
    }
}
 

[C++]Oracle資料庫存取函式(OCCI)


開發環境

  • VS2008
  • Oracle 10g Express Edition

下載OCCI函式庫

  1. 下載occivc9win32-111060-132181.zip,解壓縮到自行建立的lib目錄後可以得到目錄
  2. 下載instantclient-sdk-win32-11.2.0.1.0.zip,解壓縮後可在[instantclient_11_2\sdk\]目錄找到[include]
  3. 將上述兩個目錄複製到某個目錄下,如[D:\Project\CPPProject\occivc9win32-111060-132181]

設定開發專案

  1. 將[lib]目錄中的oraocci11.dll與oraocci11d.dll都複製到[C:\WINDOWS\system32]
  2. 於開發用的C++專案設定屬性:展開[組態屬性→C/C++→一般],修改[其他Include目錄],指到[include]目錄
  3. 展開[組態屬性→連結器→一般],修改[其他程式庫目錄],指到lib目錄
  4. 展開[組態屬性→連結器→輸入],修改[其他相依性],,增加[oraocci11d.lib]

資料庫連線函式庫

  1. OracleIO.h
    #pragma once
    #include
    namespace commonio {
     class OracleIO
     {
      private:
       oracle::occi::Environment *env;
       oracle::occi::Connection *conn;
       oracle::occi::Statement *stmt;
       oracle::occi::ResultSet *rs;
       const char* _ip;
       unsigned int _port;
       const char* _account;
       const char* _pswd;
       const char* _defaultDB;
      public:
       OracleIO(const char* ip,unsigned int port,const char* account,const char* pswd,const char* defaultDB);
       ~OracleIO(void);
    
       
       /**
       **取得連線
       **/
       oracle::occi::Connection *getConn();
       void closeConn();
       void closeStatement();
       /**
       **執行查詢
       **/
       oracle::occi::ResultSet *executeQuery(const char* sqlStr);
       /**
       **執行新增、更新、刪除
       **/
       unsigned int executeUpdate(const char* sqlStr);
     };
    };
  2. OracleIO.cpp
    #include "StdAfx.h"
    #include "OracleIO.h"
    #include "CommonFunc.h"
    #include 
    using namespace std;
    using namespace commonio;
    using namespace oracle::occi;
    OracleIO::OracleIO(const char* ip,unsigned int port,const char* account,const char* pswd,const char* defaultDB)
    {
     _ip=ip;
     _port=port;
     _account=account;
     _pswd=pswd;
     _defaultDB=defaultDB;
     env = oracle::occi::Environment::createEnvironment("UTF8","UTF8",Environment::THREADED_MUTEXED);
     conn=NULL;
     stmt=NULL;
     rs=NULL;
    }
    
    
    
    OracleIO::~OracleIO(void)
    {
     closeConn();
     oracle::occi::Environment::terminateEnvironment(env);
    }
    
    Connection* OracleIO::getConn(){
     if(conn==NULL){
      string port;
      commonio::CommonFunc::itostr(_port,port,10);
      string connectString="//";
      connectString=connectString + _ip+ ":" + port + "/" + _defaultDB;
      conn = env->createConnection(_account, _pswd, connectString);
     }
     return conn;
    }
    void OracleIO::closeConn(){
     if(conn!=NULL){
      closeStatement();
      env->terminateConnection(conn);
      conn=NULL;
     }
    }
    void OracleIO::closeStatement(){
     if(stmt!=NULL){
      if(rs!=NULL){
       stmt->closeResultSet(rs);
       rs=NULL;
      }
      conn->terminateStatement(stmt);
      stmt=NULL;
     }
    }
    
    ResultSet *OracleIO::executeQuery(const char* sqlStr){
     try{
      getConn();
      string sql=string(sqlStr);
      stmt = conn->createStatement(sql);
      rs = stmt->executeQuery();  
     }catch (SQLException &sqlExcp){
      cerr <createStatement(sql);
      result=stmt->executeUpdate();
      closeStatement();
     }catch (SQLException &sqlExcp){
      cerr <
  3. 額外函式
    • CommonFunc.h
      #pragma once
      using namespace std;
      namespace commonio {
       class CommonFunc
       {
       public:
        static void itostr(int value, std::string& buf, int base);
       };
      };
    • CommonFunc.cpp
      #include "stdafx.h"
      #include 
      #include "CommonFunc.h"
      using namespace std;
      using namespace commonio;
      
      void CommonFunc::itostr(int value, std::string& buf, int base){
       
       int i = 30;
       
       buf = "";
       
       for(; value && i ; --i, value /= base) buf = "0123456789abcdef"[value % base] + buf;
       
      }

使用範例

#include "stdafx.h"
#include 
#include 
#include "OracleIO.h"
using namespace std;
using namespace commonio;

int main(int argc, _TCHAR* argv[])
{

 OracleIO oracleio=OracleIO("localhost",1521,"oracle","oracle","XE");
 /**
 **更新測試Start
 **/ 
 unsigned int changeNum= oracleio.executeUpdate("update test1 set testname='test123' where testsn=1");
 cout<<"changeNum:"< listOfColumns =rs->getColumnListMetaData();
 for(int i=0;inext())
 {
  for(int i=0;igetString(i+1)<<"\t";
  }
  cout <

[C++]MySQL資料庫存取函式(MySQL++)

序言

此篇為研究C++存取MySQL所寫的函式。

環境

編譯MySQL++函式庫

  1. 下載mysql++-3.1.0.tar.gz,解壓縮後可以得到[mysql++-3.1.0]目錄
  2. 進入[mysql++-3.1.0\vc2008\]目錄會找到[mysql++_mysqlpp.vcproj]專案,以Visual Studio 2008開啟
  3. 編譯時MySQL++會需要MySQL的版本定義標頭檔,函式庫預設MySQL安裝於[C:\Program Files\MySQL\MySQL Server 5.1],所以需先確認是否有[C:\Program Files\MySQL\MySQL Server 5.1\include]與[C:\Program Files\MySQL\MySQL Server 5.1\lib\opt]是否存在,如果MySQL放在其他目錄,可透過專案屬性修改
    • 開啟專案屬性
    • 展開[組態屬性→C/C++→一般],修改[其他Include目錄],指到MySQL的安裝目錄中的include資料夾
    • 展開[組態屬性→連結器→一般],修改[其他程式庫目錄],指到MySQL的安裝目錄中的lib\opt資料夾
  4. 建置專案
  5. 建置成功後會在[mysql++-3.1.0\vc2008\Debug]目錄下看到編譯完成的mysqlpp_d.dll、mysqlpp_d.lib

設定開發專案

  1. 將上一步產生的[mysqlpp_d.dll]複製到[C:\WINDOWS\system32]
  2. 於開發用的C++專案設定屬性:展開[組態屬性→C/C++→一般],修改[其他Include目錄],指到MySQL的安裝目錄中的include資料夾與mysql++函式庫的lib目錄
  3. 展開[組態屬性→連結器→一般],修改[其他程式庫目錄],指到MySQL的安裝目錄中的lib\opt資料夾與mysql++編譯後的Debug目錄
  4. 展開[組態屬性→連結器→輸入],修改[其他相依性],,增加[mysqlpp_d.lib]與 [libmysql.lib]

資料庫連線函式庫

  1. MySQLIO.h
    #pragma once
    
    #include 
    
    namespace commonio {
    
         class MySQLIO
    
         {
    
         private:
    
               mysqlpp::Connection _conn;
    
               const char* _ip;
    
               unsigned int _port;
    
               const char* _account;
    
               const char* _pswd;
    
               const char* _defaultDB;
    
               const char* _error;
    
               int _errnum;
    
         public:
    
               /**
    
               **MySQL資料庫連線物件
    
               **/
    
               MySQLIO(const char* ip,unsigned int port,const char* account,const char* pswd,const char* defaultDB);
    
               ~MySQLIO(void);
    
               /**
    
               **錯誤訊息
    
               **/
    
               const char* error();
    
               int errnum();
    
               /**
    
               **取得連線
    
               **/
    
               mysqlpp::Connection getConn(){return _conn;}
    
               /**
    
               **執行查詢
    
               **/
    
               mysqlpp::StoreQueryResult executeQuery(const char* sqlStr);
    
               /**
    
               **執行查詢
    
               **/
    
               mysqlpp::StoreQueryResult executeQuery(const char* sqlStr,mysqlpp::SQLQueryParms & param);
    
               /**
    
               **執行新增、更新、刪除
    
               **/
    
               mysqlpp::SimpleResult executeUpdate(const char* sqlStr);
    
               /**
    
               **執行新增、更新、刪除
    
               **/
    
               mysqlpp::SimpleResult executeUpdate(const char* sqlStr,mysqlpp::SQLQueryParms & param);
    
         };
    
    };
  2. MySQLIO.cpp
    #include "stdafx.h"
    
    #include "MySQLIO.h"
    
     
    
    using namespace std;
    
    using namespace commonio;
    
    MySQLIO::MySQLIO(const char* ip,unsigned int port,const char* account,const char* pswd,const char* defaultDB):_conn(false)
    
    {
    
         _ip=ip;
    
         _port=port;
    
         _account=account;
    
         _pswd=pswd;
    
         _defaultDB=defaultDB;
    
         _conn.set_option(new mysqlpp::SetCharsetNameOption("utf8") );
    
    }
    
    const char* MySQLIO::error(){return _error;}
    
    int MySQLIO::errnum(){return _errnum;}
    
    mysqlpp::StoreQueryResult MySQLIO::executeQuery(const char* sqlStr){
    
         _error=NULL;
    
         _errnum=0;
    
         
    
         try{
    
               if(!_conn.connected()) {
    
                    if(!_conn.connect(_defaultDB, _ip,
    
                         _account, _pswd,_port)){
    
                               _error=_conn.error();
    
                               _errnum=_conn.errnum();
    
                               
    
                    }
    
               }
    
               if(_conn.connected()) {
    
                    mysqlpp::Query query = _conn.query(sqlStr);
    
                    if (mysqlpp::StoreQueryResult res = query.store()) {
    
                         query.reset();
    
                         return res;
    
                    }else{
    
                         _error=query.error();
    
                         _errnum=query.errnum();
    
                         
    
                    }
    
               }
    
         }catch(const mysqlpp::ConnectionFailed &e){
    
               _error=e.what();
    
               _errnum=e.errnum();
    
         }catch(const mysqlpp::BadQuery &e){        
    
               _error=e.what();
    
               _errnum=e.errnum();
    
         }catch (const mysqlpp::BadConversion & e) {
    
               _error=e.what();
    
         }catch (const mysqlpp::BadFieldName & e) {
    
               _error=e.what();
    
         }catch (const mysqlpp::BadIndex & e) {
    
               _error=e.what();
    
         }catch (const mysqlpp::BadInsertPolicy & e) {
    
               _error=e.what();
    
         }catch (const mysqlpp::BadOption & e) {
    
               _error=e.what();
    
         }catch (const mysqlpp::BadParamCount & e) {
    
               _error=e.what();
    
         }catch (const mysqlpp::Exception& e) {
    
               _error=e.what();
    
         }
    
         return mysqlpp::StoreQueryResult();
    
     
    
    }
    
    mysqlpp::StoreQueryResult MySQLIO::executeQuery(const char* sqlStr,mysqlpp::SQLQueryParms & param){
    
         _error=NULL;
    
         _errnum=0;
    
         
    
         try{
    
               if(!_conn.connected()) {
    
                    if(!_conn.connect(_defaultDB, _ip,
    
                         _account, _pswd,_port)){
    
                               _error=_conn.error();
    
                               _errnum=_conn.errnum();
    
                               
    
                    }
    
               }
    
               if(_conn.connected()) {
    
                    mysqlpp::Query query = _conn.query(sqlStr);
    
                    query.parse();
    
                    if (mysqlpp::StoreQueryResult res = query.store(param)) {
    
                         query.reset();
    
                         return res;
    
                    }else{
    
                         _error=query.error();
    
                         _errnum=query.errnum();
    
                         
    
                    }
    
               }
    
         }catch(const mysqlpp::ConnectionFailed &e){
    
               _error=e.what();
    
               _errnum=e.errnum();
    
         }catch(const mysqlpp::BadQuery &e){        
    
               _error=e.what();
    
               _errnum=e.errnum();
    
         }catch (const mysqlpp::BadConversion & e) {
    
               _error=e.what();
    
         }catch (const mysqlpp::BadFieldName & e) {
    
               _error=e.what();
    
         }catch (const mysqlpp::BadIndex & e) {
    
               _error=e.what();
    
         }catch (const mysqlpp::BadInsertPolicy & e) {
    
               _error=e.what();
    
         }catch (const mysqlpp::BadOption & e) {
    
               _error=e.what();
    
         }catch (const mysqlpp::BadParamCount & e) {
    
               _error=e.what();
    
         }catch (const mysqlpp::Exception& e) {
    
               _error=e.what();
    
         }
    
         return mysqlpp::StoreQueryResult();
    
    }
    
     
    
     
    
    mysqlpp::SimpleResult MySQLIO::executeUpdate(const char* sqlStr){
    
         _error=NULL;
    
         _errnum=0;
    
         
    
         try{
    
               if(!_conn.connected()) {
    
                    if(!_conn.connect(_defaultDB, _ip,
    
                         _account, _pswd,_port)){
    
                               _error=_conn.error();
    
                               _errnum=_conn.errnum();
    
                    }
    
               }
    
               if(_conn.connected()) {
    
                    mysqlpp::Query query = _conn.query(sqlStr);
    
                    query.parse();
    
                    if (mysqlpp::SimpleResult res = query.execute()) {
    
                         query.reset();
    
                         return res;
    
                    }else{
    
                         _error=query.error();
    
                         _errnum=query.errnum();
    
                         
    
                    }
    
               }
    
         }catch(const mysqlpp::ConnectionFailed &e){
    
               _error=e.what();
    
               _errnum=e.errnum();
    
         }catch(const mysqlpp::BadQuery &e){        
    
               _error=e.what();
    
               _errnum=e.errnum();
    
         }catch (const mysqlpp::BadConversion & e) {
    
               _error=e.what();
    
         }catch (const mysqlpp::BadFieldName & e) {
    
               _error=e.what();
    
         }catch (const mysqlpp::BadIndex & e) {
    
               _error=e.what();
    
         }catch (const mysqlpp::BadInsertPolicy & e) {
    
               _error=e.what();
    
         }catch (const mysqlpp::BadOption & e) {
    
               _error=e.what();
    
         }catch (const mysqlpp::BadParamCount & e) {
    
               _error=e.what();
    
         }catch (const mysqlpp::Exception& e) {
    
               _error=e.what();
    
         }
    
         return mysqlpp::SimpleResult();
    
    }
    
     
    
    mysqlpp::SimpleResult MySQLIO::executeUpdate(const char* sqlStr,mysqlpp::SQLQueryParms & param){
    
         _error=NULL;
    
         _errnum=0;
    
         
    
         try{
    
               if(!_conn.connected()) {
    
                    if(!_conn.connect(_defaultDB, _ip,
    
                         _account, _pswd,_port)){
    
                               _error=_conn.error();
    
                               _errnum=_conn.errnum();
    
                    }
    
               }
    
               if(_conn.connected()) {
    
                    mysqlpp::Query query = _conn.query(sqlStr);
    
                    query.parse();
    
                    if (mysqlpp::SimpleResult res = query.execute(param)) {
    
                         query.reset();
    
                         return res;
    
                    }else{
    
                         _error=query.error();
    
                         _errnum=query.errnum();
    
                         
    
                    }
    
               }
    
         }catch(const mysqlpp::ConnectionFailed &e){
    
               _error=e.what();
    
               _errnum=e.errnum();
    
         }catch(const mysqlpp::BadQuery &e){        
    
               _error=e.what();
    
               _errnum=e.errnum();
    
         }catch (const mysqlpp::BadConversion & e) {
    
               _error=e.what();
    
         }catch (const mysqlpp::BadFieldName & e) {
    
               _error=e.what();
    
         }catch (const mysqlpp::BadIndex & e) {
    
               _error=e.what();
    
         }catch (const mysqlpp::BadInsertPolicy & e) {
    
               _error=e.what();
    
         }catch (const mysqlpp::BadOption & e) {
    
               _error=e.what();
    
         }catch (const mysqlpp::BadParamCount & e) {
    
               _error=e.what();
    
         }catch (const mysqlpp::Exception& e) {
    
               _error=e.what();
    
         }
    
         return mysqlpp::SimpleResult();
    
    }
    
     
    
    MySQLIO::~MySQLIO(void)
    
    {    
    
    }

使用範例

#include "stdafx.h"

#include 

#include "MySQLIO.h"

using namespace std;

using namespace commonio;

 

int main(int argc, _TCHAR* argv[])

{

     string data;

 

     MySQLIO mysqlio("localhost",3306,"root",NULL,"pklogdb");

     mysqlpp::SQLQueryParms params;

           params << 2;

     if (mysqlpp::StoreQueryResult res = mysqlio.executeQuery("select * from gametypetab where gameType=%0q",params)) {

           mysqlpp::StoreQueryResult::const_iterator it;

           mysqlpp::Row::const_iterator colit;

           for (it = res.begin(); it != res.end(); ++it) {

                mysqlpp::Row row = *it;

                cout << '\t';

                for (colit = row.begin(); colit != row.end(); ++colit) {

                     if(colit->is_null()){

                           cout << "\t (NULL)"<< endl;

                     }else{

                           string col(*colit);

                           cout << '\t' << col << endl;                         

                     }

                }

                cout << endl;

           }

           params.clear();

           string value("TEST");

           params<0){

                cerr << "success update"<< endl;

           }

     }else{

           cerr << "Failed to get item list: "<< endl;

           return 1;

     }

 

    return 0;

}

[Java]MySQL/Oracle資料庫存取函式

序言

延續上一篇,這篇針對MySQL資料庫的存取寫出的函式提供給大家參考,開發環境與資料庫連接器的設定可參考上一篇。
我在這邊有兩種建立連線物件的方式,預設是來自JNDI的連線設定,另一種是直接產生的方式,可在建立物件時做選擇。
使用範例的部分我改用JUnit來進行我自己的原始碼驗證,大家可直接參考呼叫的方式。
PS.2011/6/21 更新,加入Oracle的連線方法(但分頁查詢的函式只能用在MySQL)

原始碼函式類別

package common;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;

import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;

public class DBBaseIO {
private static boolean _isDebug=false;
public enum DBType{
MySQL
,Oracle
}

public static void setDebug(boolean isDebug) {
_isDebug = isDebug;
}

public static boolean isIsdebug() {
return _isDebug;
}

private Connection con = null; // Database objects
public Connection getConnection() {
return con;
}

private Statement stat = null;
private ResultSet rs = null;
private PreparedStatement pst = null;
private boolean isClosed=false;
public boolean isClosedConn(){
return isClosed;
}

protected void finalize () {
if(!isClosed)CloseConn();
}

/**
* 建立資料庫存取物件(使用JNDI XML設定,名稱為MySqlDS)
* @throws SQLException
* @throws NamingException
*/
public DBBaseIO() throws SQLException, NamingException {
setupConnMySQLByXML();
}
/**
* 建立資料庫存取物件(使用JNDI XML設定)
* @param dsName 設定名稱
* @throws SQLException
* @throws NamingException
*/
public DBBaseIO(String dsName) throws SQLException, NamingException {
setupConnMySQLByXML(dsName);
}
/**
*
* @param sourceType
* @throws ClassNotFoundException
* @throws SQLException
* @throws NamingException
*/
public DBBaseIO(int sourceType) throws ClassNotFoundException, SQLException, NamingException{
switch(sourceType){
case 0:
setupConnMySQL("localhost:3306", "root", "", "mysql");
break;
case 1:
setupConnMySQLByXML();
break;
}
}
/**
* 建立資料庫存取物件
*
* @param str_SQLIP
* 資料庫IP
* @param str_SQLID
* 登入帳號
* @param str_SQLPSWD
* 登入密碼
* @param str_SQLDefaultDBName
* 預設資料庫
* @throws SQLException
* @throws ClassNotFoundException
*/
public DBBaseIO(String str_SQLIP, String str_SQLID, String str_SQLPSWD,
String str_SQLDefaultDBName) throws ClassNotFoundException, SQLException {
setupConnMySQL(str_SQLIP, str_SQLID, str_SQLPSWD, str_SQLDefaultDBName);
}
/**
* 建立資料庫存取物件
*
* @param dbtype
* 資料庫類型
* @param str_SQLIP
* 資料庫IP
* @param str_SQLID
* 登入帳號
* @param str_SQLPSWD
* 登入密碼
* @param str_SQLDefaultDBName
* 預設資料庫
* @throws SQLException
* @throws ClassNotFoundException
*/
public DBBaseIO(DBType dbtype,String str_SQLIP, String str_SQLID, String str_SQLPSWD,
String str_SQLDefaultDBName) throws ClassNotFoundException, SQLException {
if(dbtype==DBType.MySQL)
setupConnMySQL(str_SQLIP, str_SQLID, str_SQLPSWD, str_SQLDefaultDBName);
else if(dbtype==DBType.Oracle)
setupConnOracle(str_SQLIP, str_SQLID, str_SQLPSWD, str_SQLDefaultDBName);
else
throw new ClassNotFoundException("DBType un-define");
}
private void setupConnMySQLByXML() throws NamingException, SQLException{setupConnMySQLByXML("MySqlDS"); }
private void setupConnMySQLByXML(String name) throws NamingException, SQLException{
if(isIsdebug()){
System.out.println("DataSource:"+"java:/" + name);
}

try{
InitialContext ctx = new InitialContext();
DataSource ds = (DataSource)ctx.lookup("java:/" + name);
con = ds.getConnection();
} catch (NamingException e) {
System.err.println("Connection XML Load Error :" + e.toString());
throw e;
} catch (SQLException e) {
System.err.println("Get Connection Error :" + e.toString());
throw e;
}
}

private void setupConnMySQL(String str_SQLIP, String str_SQLID,
String str_SQLPSWD, String str_SQLDefaultDBName) throws ClassNotFoundException,SQLException {
if(isIsdebug()){
System.out.println("DataSource:"+"jdbc:mysql://" + str_SQLIP + "/"
+ str_SQLDefaultDBName
+ "?useUnicode=true&characterEncoding=UTF8");
System.out.println("ID:"+str_SQLID+"\tPassword:"+str_SQLPSWD);
System.out.println("JDBC Driver:" + "com.mysql.jdbc.Driver");
}
try {
Class.forName("com.mysql.jdbc.Driver");

con = DriverManager.getConnection("jdbc:mysql://" + str_SQLIP + "/"
+ str_SQLDefaultDBName
+ "?useUnicode=true&characterEncoding=UTF8", str_SQLID,
str_SQLPSWD);

} catch (ClassNotFoundException e) {
System.err.println("DriverClassNotFound :" + e.toString());
throw e;
}
catch (SQLException x) {
System.err.println("Exception :" + x.toString());
throw x;
}
}
private void setupConnOracle(String str_SQLIP, String str_SQLID,
String str_SQLPSWD, String str_SQLDefaultDBName) throws ClassNotFoundException,SQLException {
if(isIsdebug()){
System.out.println("DataSource:"+"jdbc:oracle:thin:"+str_SQLID+"/"+str_SQLPSWD+"@//" + str_SQLIP + "/"
+ str_SQLDefaultDBName);
}
try {
Class.forName("oracle.jdbc.OracleDriver");

con = DriverManager.getConnection("jdbc:oracle:thin:"+str_SQLID+"/"+str_SQLPSWD+"@//" + str_SQLIP + "/"
+ str_SQLDefaultDBName);

} catch (ClassNotFoundException e) {
System.err.println("DriverClassNotFound :" + e.toString());
throw e;
}
catch (SQLException x) {
System.err.println("Exception :" + x.toString());
throw x;
}
}

/**
* 執行insert update delete等更新指令用
*
* @param str_SQL
* 查詢語法
* @return 資料庫變動筆數
*/
public int executeUpdate(String str_SQL) throws SQLException,NullPointerException {
return executeUpdate(str_SQL, null);
}

/**
* 執行insert update delete等更新指令用
*
* @param str_SQL
* 查詢語法
* @param param
* 參數設定,SQL語法中以?指定,順序即為?的順序,如 where name=? (此參數可為null)
* @return 資料庫變動筆數
*/
public int executeUpdate(String str_SQL, Object[] param) throws SQLException ,NullPointerException{
return executeUpdate(str_SQL, param, true);
}

/**
* 執行insert update delete等更新指令用
*
* @param str_SQL
* 查詢語法
* @param param
* 參數設定,SQL語法中以?指定,順序即為?的順序,如 where name=? (此參數可為null)
* @param isCloseConn
* 是否關閉連線
* @return 資料庫變動筆數
*/
public int executeUpdate(String str_SQL, Object[] param, boolean isCloseConn) throws SQLException,NullPointerException {
if(isIsdebug()){
System.out.println("executeUpdate:"+str_SQL);
if(param!=null)
for(int i=0;i<param.length;i++)
System.out.println("Parameter "+ i +":"+param[i]);
System.out.println("isCloseConn :"+isCloseConn);
}

int result = 0;
if (con != null) {
try {
int i = 0;
if (param == null) {
stat = con.createStatement();
result = stat.executeUpdate(str_SQL);
} else {
pst = con.prepareStatement(str_SQL);
for (i = 0; i < param.length; i++) {
pst.setObject(i + 1, param[i]);
}
result = pst.executeUpdate();
try {
pst.clearParameters();
} catch (Exception e) {
CloseConn();
}
}
} catch (SQLException e) {
System.err.println("executeUpdate Exception :" + e.toString());
throw e;
} finally {
CloseConn(isCloseConn);
}
} else {
System.err.println("Connection is null");
throw new NullPointerException("Connection is null");
}
return result;
}


/**
* 批次執行SQL指令使用
*
* @param str_SQL
* 查詢語法的陣列
* @param isCloseConn
* 是否關閉連線
* @return 資料庫變動筆數的陣列
*/
public int[] executeBatch(String[] str_SQL, boolean isCloseConn) throws SQLException,NullPointerException {
if(isIsdebug()){
System.out.println("executeBatch:"+str_SQL);
}

int[] result=null;
if (con != null) {
try {
int i = 0;
stat = con.createStatement();
for (i = 0; i < str_SQL.length; i++) {
stat.addBatch(str_SQL[i]);
}
result=stat.executeBatch();
if(isIsdebug()){
System.out.println("executeBatch result:");
for (i = 0; i < result.length; i++) {
System.out.println(i+":"+result[i]);
}
}
} catch (SQLException e) {
System.err.println("executeBatch Exception :" + e.toString());
throw e;
} finally {
CloseConn(isCloseConn);
}
} else {
System.err.println("Connection is null");
throw new NullPointerException("Connection is null");
}
return result;
}

/**
* 批次執行SQL指令使用
* @param str_SQL 查詢語法
* @param param 以相同數量的參數形成的ArrayList
* @param isCloseConn 是否關閉連線
* @return 資料庫變動筆數的陣列
* @throws SQLException
* @throws NullPointerException
*/
public int[] addBatch(String str_SQL, ArrayList<Object[]> param, boolean isCloseConn) throws SQLException,NullPointerException {

int i = 0;
int j = 0;
if(isIsdebug()){
System.out.println("executeBatch:"+str_SQL);
if(param!=null)
for (i = 0; i < param.size(); i++) {
for (j = 0;j < param.get(i).length; j++) {
System.out.println("Parameter "+ i+","+j +":"+param.get(i)[j]);
}
}
}

int[] result=null;
if (con != null) {
try {
pst = con.prepareStatement(str_SQL);
for (i = 0; i < param.size(); i++) {
for (j = 0;j < param.get(i).length; j++) {
pst.setObject(j + 1, param.get(i)[j]);
}
pst.addBatch();
}
result=pst.executeBatch();
if(isIsdebug()){
System.out.println("executeBatch result:");
for (i = 0; i < result.length; i++) {
System.out.println(i+":"+result[i]);
}
}
} catch (SQLException e) {
System.err.println("executeBatch Exception :" + e.toString());
throw e;
} finally {
CloseConn(isCloseConn);
}
} else {
System.err.println("Connection is null");
throw new NullPointerException("Connection is null");
}

return result;
}

/**
* 查詢資料
*
* @param str_SQL
* 查詢語法
* @return 每列一筆資料,每筆資料的欄位存於 Object Array中
*/
public ArrayList<Object[]> executeQuery(String str_SQL) throws SQLException,NullPointerException {
return executeQuery(str_SQL, null);
}
/**
* 查詢資料
*
* @param str_SQL
* 查詢語法
* @param param
* 參數設定,SQL語法中以?指定,順序即為?的順序,如 where name=? (此參數可為null)
* @return 每列一筆資料,每筆資料的欄位存於 Object Array中
*/
public ArrayList<Object[]> executeQuery(String str_SQL, Object[] param) throws SQLException,NullPointerException {
return executeQuery(str_SQL, param, true);
}

/**
* 查詢資料
*
* @param str_SQL
* 查詢語法
* @param param
* 參數設定,SQL語法中以?指定,順序即為?的順序,如 where name=? (此參數可為null)
* @param isCloseConn
* 是否關閉連線
* @return 每列一筆資料,每筆資料的欄位存於 Object Array中
*/
public ArrayList<Object[]> executeQuery(String str_SQL, Object[] param,
boolean isCloseConn) throws SQLException,NullPointerException {
if(isIsdebug()){
System.out.println("executeQuery:"+str_SQL);
if(param!=null)
for(int i=0;i<param.length;i++)
System.out.println("Parameter "+ i +":"+param[i]);
System.out.println("isCloseConn :"+isCloseConn);
}
ArrayList<Object[]> result = new ArrayList<Object[]>();
if (con != null) {
try {
int i = 0;
if (param == null) {
stat = con.createStatement();
rs = stat.executeQuery(str_SQL);
} else {
pst = con.prepareStatement(str_SQL);
for (i = 0; i < param.length; i++) {
pst.setObject(i + 1, param[i]);
}
rs = pst.executeQuery();
pst.clearParameters();
}

ArrayList<Object> arr;
ResultSetMetaData rsMetaData = rs.getMetaData();
int numberOfColumns = rsMetaData.getColumnCount();
while (rs.next()) {
arr = new ArrayList<Object>();
for (i = 1; i < numberOfColumns + 1; i++) {
arr.add(rs.getObject(i));
}
result.add(arr.toArray());
}
} catch (SQLException e) {
System.err.println("executeQuery Exception :" + e.toString());
throw e;
} finally {
CloseConn(isCloseConn);
}
} else {
System.err.println("Connection is null");
throw new NullPointerException("Connection is null");
}
return result;
}

/**
* 查詢資料(請記得要關閉Result Set)
*
* @param str_SQL
* 查詢語法
* @return 回傳查詢得到的result set
*/
public ResultSet executeQueryResultset(String str_SQL) throws SQLException,NullPointerException {
return executeQueryResultset(str_SQL,null);
}
/**
* 查詢資料(請記得要關閉Connection)
*
* @param str_SQL
* 查詢語法
* @param param
* 參數設定,SQL語法中以?指定,順序即為?的順序,如 where name=? (此參數可為null)
* @return 回傳查詢得到的result set
*/
public ResultSet executeQueryResultset(String str_SQL, Object[] param) throws SQLException,NullPointerException {
if(isIsdebug()){
System.out.println("executeQuery:"+str_SQL);
if(param!=null)
for(int i=0;i<param.length;i++)
System.out.println("Parameter "+ i +":"+param[i]);
}

ResultSet result = null;
if (con != null) {
try {
int i = 0;
if (param == null) {
stat = con.createStatement();
rs = stat.executeQuery(str_SQL);
} else {
pst = con.prepareStatement(str_SQL);
for (i = 0; i < param.length; i++) {
pst.setObject(i + 1, param[i]);
}
rs = pst.executeQuery();
pst.clearParameters();
}

result=rs;
} catch (SQLException e) {
System.err.println("executeQueryResultset Exception :" + e.toString());
throw e;
}
} else {
System.err.println("Connection is null");
throw new NullPointerException("Connection is null");
}
return result;
}

/**
* 查詢資料,並傳回查詢所傳回的結果集第一個資料列的第一個資料行
*
* @param str_SQL
* 查詢語法
* @return 每列一筆資料,每筆資料的欄位存於 Object Array中
*/
public Object executescalar(String str_SQL) throws SQLException,NullPointerException {
return executescalar(str_SQL, null);
}
/**
* 查詢資料,並傳回查詢所傳回的結果集第一個資料列的第一個資料行
*
* @param str_SQL
* 查詢語法
* @param param
* 參數設定,SQL語法中以?指定,順序即為?的順序,如 where name=? (此參數可為null)
* @return 每列一筆資料,每筆資料的欄位存於 Object Array中
*/
public Object executescalar(String str_SQL, Object[] param) throws SQLException,NullPointerException {
return executescalar(str_SQL, param, true);
}

/**
* 查詢資料,並傳回查詢所傳回的結果集第一個資料列的第一個資料行
*
* @param str_SQL
* 查詢語法
* @param param
* 參數設定,SQL語法中以?指定,順序即為?的順序,如 where name=? (此參數可為null)
* @param isCloseConn
* 是否關閉連線
* @return 每列一筆資料,每筆資料的欄位存於 Object Array中
*/
public Object executescalar(String str_SQL, Object[] param,
boolean isCloseConn) throws SQLException,NullPointerException {
if(isIsdebug()){
System.out.println("executeQuery:"+str_SQL);
if(param!=null)
for(int i=0;i<param.length;i++)
System.out.println("Parameter "+ i +":"+param[i]);
System.out.println("isCloseConn :"+isCloseConn);
}
Object result = null;
if (con != null) {
try {
int i = 0;
if (param == null) {
stat = con.createStatement();
rs = stat.executeQuery(str_SQL);
} else {
pst = con.prepareStatement(str_SQL);
for (i = 0; i < param.length; i++) {
pst.setObject(i + 1, param[i]);
}
rs = pst.executeQuery();
pst.clearParameters();
}

ResultSetMetaData rsMetaData = rs.getMetaData();
int numberOfColumns = rsMetaData.getColumnCount();
if (rs.next() && numberOfColumns>=1) {
result=rs.getObject(1);
}
} catch (SQLException e) {
System.err.println("executescalar Exception :" + e.toString());
throw e;
} finally {
CloseConn(isCloseConn);
}
} else {
System.err.println("Connection is null");
throw new NullPointerException("Connection is null");
}
return result;
}


/**
* 執行SQL
*
* @param str_SQL
* 查詢語法
* @return 是否成功
*/
public boolean execute(String str_SQL) throws SQLException,NullPointerException {
return execute(str_SQL, null);
}

/**
* 執行SQL
*
* @param str_SQL
* 查詢語法
* @param param
* 參數設定,SQL語法中以?指定,順序即為?的順序,如 where name=? (此參數可為null)
* @return 是否成功
*/
public boolean execute(String str_SQL, Object[] param) throws SQLException,NullPointerException {
return execute(str_SQL, param, true);
}

/**
* 執行SQL
*
* @param str_SQL
* 查詢語法
* @param param
* 參數設定,SQL語法中以?指定,順序即為?的順序,如 where name=? (此參數可為null)
* @param isCloseConn
* 是否關閉連線
* @return 是否成功
*/
public boolean execute(String str_SQL, Object[] param, boolean isCloseConn) throws SQLException,NullPointerException {
if(isIsdebug()){
System.out.println("executeQuery:"+str_SQL);
if(param!=null)
for(int i=0;i<param.length;i++)
System.out.println("Parameter "+ i +":"+param[i]);
System.out.println("isCloseConn :"+isCloseConn);
}
boolean result = false;
if (con != null) {
try {
int i = 0;
if (param == null) {
stat = con.createStatement();
result = stat.execute(str_SQL);
} else {
pst = con.prepareStatement(str_SQL);
for (i = 0; i < param.length; i++) {
pst.setObject(i + 1, param[i]);
}
result = pst.execute();
pst.clearParameters();
}
} catch (SQLException e) {
System.err.println("execute Exception :" + e.toString());
throw e;
} finally {
CloseConn(isCloseConn);
}
} else {
System.err.println("Connection is null");
throw new NullPointerException("Connection is null");
}
return result;
}
/**
* 關閉連線
*/
public void CloseConn() {
CloseConn(true);
}

/**
* 關閉連線
* @param isCloseConn 是否關閉Connection
*/
public void CloseConn(boolean isCloseConn) {
if(isIsdebug()){
System.out.println("CloseConn:"+isCloseConn);
}
try {
if (rs != null) {
rs.close();
rs = null;
}
if (stat != null) {
stat.close();
stat = null;
}
if (pst != null) {
pst.close();
pst = null;
}
} catch (SQLException e) {
//System.err.println("Close Exception :" + e.toString());
} finally {
try {
if (con != null && isCloseConn) {
con.close();
isClosed=true;
}
} catch (SQLException e) {
//System.err.println("Close Exception :" + e.toString());
}
}
}


int allpage=0;

public int getAllpage() {
return allpage;
}
public void setAllpage(int allpage) {
this.allpage = allpage;
}
/**
* 查詢分頁資料
* @param colunms
* @param from
* @param where
* @param group
* @param order
* @param fpage
* @param pages
* @return
* @throws SQLException
* @throws NullPointerException
*/
public ArrayList<Object[]> selectPage(String colunms,String from,String where,String group,String having,String order,int fpage,int pages) throws SQLException,NullPointerException{
return selectPage(colunms,from,where,group,having,order,fpage,pages,null);
}
/**
* 查詢分頁資料
* @param colunms
* @param from
* @param where
* @param group
* @param order
* @param fpage
* @param pages
* @param param
* @return
* @throws SQLException
* @throws NullPointerException
*/
public ArrayList<Object[]> selectPage(String colunms,String from,String where,String group,String having,String order,int fpage,int pages, Object[] param) throws SQLException,NullPointerException{
return selectPage(colunms,from,where,group,having,order,fpage,pages,param,true);
}
/**
* 查詢分頁資料
* @param colunms
* @param from
* @param where
* @param group
* @param order
* @param fpage
* @param pages
* @param param
* @param isCloseConn
* @return
* @throws SQLException
* @throws NullPointerException
*/
public ArrayList<Object[]> selectPage(String colunms,String from,String where,String group,String having,String order,int fpage,int pages, Object[] param, boolean isCloseConn) throws SQLException,NullPointerException{
return selectPage(colunms, from, where, group, having, order, fpage, pages, true, 0, param, isCloseConn);
}
/**
* 查詢分頁資料
* @param colunms
* @param from
* @param where
* @param group
* @param having
* @param order
* @param fpage
* @param pages
* @param isCountPage
* @param allpageCount
* @param param
* @param isCloseConn
* @return
* @throws SQLException
* @throws NullPointerException
*/
public ArrayList<Object[]> selectPage(String colunms,String from,String where,String group,String having,String order,int fpage,int pages,boolean isCountPage,int allpageCount, Object[] param, boolean isCloseConn) throws SQLException,NullPointerException{
ArrayList<Object[]> result=null;
try{
String sql;
if(!isCountPage){
allpage=allpageCount;
}else{
int intRowCount;
sql="select count(*) from (select ";
if(colunms!=null){
sql+="" + colunms + " \n ";
}else{
sql+="* \n ";
}
sql+="from " + from.toString() + " \n ";
if(where!=null){
sql+="where " + where + " \n ";
}
if(group!=null){
sql+="group by " + group + " \n ";
}
if(having!=null){
sql+="having " + group + " \n ";
}
sql+=") selectcount \n ";

Object temp=executescalar(sql,param,false);
if(temp==null){
return result;
}
intRowCount=Integer.parseInt(temp.toString());
allpage=(intRowCount+fpage-1) / fpage;
}
int spage;

if(pages > allpage ){// pages == 0){
pages = 1;
}
spage=(pages-1)*fpage;
//sql="select " + colunms + " \n from " + from + " \n where " + where + " \n order by " + order + " \n limit "+ spage +","+fpage ;
sql="select ";
if(colunms!=null){
sql+= colunms + " \n ";
}else{
sql+="* \n ";
}
sql+="from " + from + " \n ";
if(where!=null){
sql+="where " + where + " \n ";
}
if(group!=null){
sql+="group by " + group + " \n ";
}
if(having!=null){
sql+="having " + group + " \n ";
}
if(order!=null){
sql+="order by " + order + " \n ";
}
sql+="limit "+ spage +","+fpage;
result=executeQuery(sql, param, false);
} catch (NullPointerException e) {
System.err.println("NullPointerException Exception :" + e.toString());
throw e;
} catch (SQLException e) {
System.err.println("SQLException Exception :" + e.toString());
throw e;
} finally {
CloseConn(isCloseConn);
}
return result;
}

}

使用範例程式

package common.test;

import static org.junit.Assert.*;

import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.ArrayList;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import common.DBBaseIO;

public class DBBaseIOTest {

DBBaseIO dbio;
int m_id;

String m_name;
@Before
public void setUp() throws Exception {
dbio=new DBBaseIO(0);
m_id=20100111;
m_name="tester" + m_id;
}

@After
public void tearDown() throws Exception {
dbio.CloseConn();
dbio=null;
}

@Test
public void testExecuteString() {
String msg="\n# testExecuteString\n Drop and Create :\t TestTable" + m_id;
System.out.println(msg);//DROP TABLE IF EXISTS TestTable" + m_id + ";
String str_Sql = "CREATE TABLE TestTable" + m_id + " ( " +
"`test_id` int(10) unsigned NOT NULL auto_increment, " +
"`member_id` int(10) unsigned NOT NULL, "+
"`member_name` varchar(45) NOT NULL, " +
"PRIMARY KEY (`test_id`) "+
") ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; ";
try{
dbio.execute(str_Sql);

}catch(Exception e){
fail(msg + "\n\n" + str_Sql + "\n\nResult:" + e.getMessage());
}
}

@Test
public void testExecuteUpdateString() {
String msg="\n# testExecuteUpdateString\n Insert :\tID=" + m_id + "\tName=" + m_name;
System.out.println(msg);
String str_Sql="Insert into TestTable" + m_id + " (member_id,member_name) values('" + m_id + "','" + m_name + "')";
try{
int result=dbio.executeUpdate(str_Sql);
if(result<=0){
fail(msg + "\n\n" + str_Sql + "\n\nResult:" + result);
}
}catch(Exception e){
fail(msg + "\n\n" + str_Sql + "\n\nResult:" + e.getMessage());
}
}

@Test
public void testExecuteQueryString() {
String msg="\n# testExecuteQueryString\n Select ALL :";
System.out.println(msg);
String str_Sql="Select * from TestTable" + m_id + "";
try{
ArrayList<Object[]> result=dbio.executeQuery(str_Sql);
if(result.size()<=0){
fail(msg + "\n\n" + str_Sql + "\n\nResult:" + result);
}else{
for(int i=0;i<result.size();i++){
for(int j=0;j<result.get(i).length;j++){
System.out.print(result.get(i)[j] + "\t");
}
System.out.println();
}
}
}catch(Exception e){
fail(msg + "\n\n" + str_Sql + "\n\nResult:" + e.getMessage());
}
}

@Test
public void testexecuteQueryResultset() {
String msg="\n# testexecuteQueryResultset\n Select ALL :";
System.out.println(msg);
String str_Sql="Select * from TestTable" + m_id + "";
try{

ResultSet rs=dbio.executeQueryResultset(str_Sql);
ResultSetMetaData rsMetaData = rs.getMetaData();
int numberOfColumns = rsMetaData.getColumnCount();
while (rs.next()) {
for (int i = 1; i < numberOfColumns + 1; i++) {
System.out.print(rs.getObject(i) + "\t");
}
System.out.println();
}

dbio.CloseConn();
}catch(Exception e){
fail(msg + "\n\n" + str_Sql + "\n\nResult:" + e.getMessage());
}
}

@Test
public void testselectPage() {
String msg="\n# testselectPage\n Insert 98 User";
System.out.println(msg);
String str_Sql="";
try{

for(int i=1;i<=98;i++){
str_Sql="Insert into TestTable" + m_id + " (member_id,member_name) values('" + m_id + i + "','" + m_name + "_" + i + "')";
int result=dbio.executeUpdate(str_Sql,null,false);
if(result<=0){
fail(msg + "\n\n" + str_Sql + "\n\nResult:" + result);
}
}
str_Sql="";
ArrayList<Object[]> result=dbio.selectPage("member_id,member_name", "TestTable" + m_id, null, "member_id", 10, 10, null, true);
if(result.size()<=0){
fail(msg + "\n\n" + str_Sql + "\n\nResult:" + result);
}else{
for(int i=0;i<result.size();i++){
for(int j=0;j<result.get(i).length;j++){
System.out.print(result.get(i)[j] + "\t");
}
System.out.println();
}
}
}catch(Exception e){
fail(msg + "\n\n" + str_Sql + "\n\nResult:" + e.getMessage());
}


}


@Test
public void testExecuteUpdateStringObjectArray() {
m_name+="_Updateed";
String msg="\n# testExecuteUpdateStringObjectArray\n Update :\tID=" + m_id + "\tName=" + m_name;
System.out.println(msg);
String str_Sql="Update TestTable" + m_id + " Set member_name=? WHERE member_id=?";
Object[] param={m_name,m_id};
try{
int result=dbio.executeUpdate(str_Sql,param);
if(result<=0){
fail(msg + "\n\n" + str_Sql + "\n\nResult:" + result);
}
}catch(Exception e){
fail(msg + "\n\n" + str_Sql + "\n\nResult:" + e.getMessage());
}
}

@Test
public void testExecuteQueryStringObjectArray() {
String msg="\n# testExecuteQueryStringObjectArray\n Select :\tID=" + m_id;
System.out.println(msg);
String str_Sql="Select * from TestTable" + m_id + " where member_id=?";
Object[] param={m_id};
try{
ArrayList<Object[]> result=dbio.executeQuery(str_Sql,param);
if(result.size()<=0){
fail(msg + "\n\n" + str_Sql + "\n\nResult:" + result);
}else{
for(int i=0;i<result.size();i++){
for(int j=0;j<result.get(i).length;j++){
System.out.print(result.get(i)[j] + "\t");
}
System.out.println();
}
}
}catch(Exception e){
fail(msg + "\n\n" + str_Sql + "\n\nResult:" + e.getMessage());
}
}

@Test
public void testExecuteUpdateStringObjectArrayBoolean() {
String msg="\n# testExecuteUpdateStringObjectArrayBoolean\n Delete :\tID=" + m_id + "\tName=" + m_name;
System.out.println(msg);
String str_Sql="Delete from TestTable" + m_id + " WHERE member_id=?";
Object[] param={m_id};
try{
int result=dbio.executeUpdate(str_Sql,param,false);
if(result<=0){
fail(msg + "\n\n" + str_Sql + "\n\nResult:" + result);
}
}catch(Exception e){
fail(msg + "\n\n" + str_Sql + "\n\nResult:" + e.getMessage());
}finally{
dbio.CloseConn();
}
}

@Test
public void testExecuteQueryStringObjectArrayBoolean() {
String msg="\n# testExecuteQueryStringObjectArrayBoolean\n Select :\tID=" + m_id;
System.out.println(msg);
String str_Sql="Select * from TestTable" + m_id + " where member_id=?";
Object[] param={m_id};
try{
ArrayList<Object[]> result=dbio.executeQuery(str_Sql,param,false);
if(result.size()>0){
for(int i=0;i<result.size();i++){
for(int j=0;j<result.get(i).length;j++){
System.out.print(result.get(i)[j] + "\t");
}
System.out.println();
}
fail(msg + "\n\n" + str_Sql + "\n\nResult:" + result);
}
}catch(Exception e){
fail(msg + "\n\n" + str_Sql + "\n\nResult:" + e.getMessage());
}finally{
dbio.CloseConn();
}
}





@Test
public void testExecuteStringObjectArrayBoolean() {
String msg="\n# testExecuteStringObjectArrayBoolean\n Drop :\t TestTable_" + m_id;
System.out.println(msg);
String str_Sql="DROP TABLE IF EXISTS TestTable" + m_id + ";" ;

try{
dbio.execute(str_Sql,null,false);

}catch(Exception e){
fail(msg + "\n\n" + str_Sql + "\n\nResult:" + e.getMessage());
}finally{
dbio.CloseConn();
}
}



}

總結

我在開發時採用ArrayList把資料給回傳回來,因此相反的就沒有辦法回傳欄位名稱(不過我想你在寫SQL時應該已經可以指定自己要用的欄位名稱了吧)。

相關文章

[JAAS] JBoss下動態網站使用資料庫設定認證授權

序言

雖說我以前一直很不想再Try Java Tool弄很久~因為開發速度還是微軟順手些,但看來我還是逃脫不了。
總之~這篇是最近我實作時的紀錄,主要是要用Java預設的安全機制,完成網站的認證授權(也就是登入登出、 Login and Logout)。
通常書到用時方恨少,這句話這時就應驗了,腦中有的資訊太少,所以這個東西花了我不少功夫。
如果有任何不標準的用法,請見諒,很多都是我從網路找來的資訊組合而成的,我很懶得去查官方的英文文件(官方文件有很多其實也沒寫的很詳細...)。
歡迎有更標準的用法的話,請留下文章、連結等資料指正我。

開發環境

JBoss設定

  1. 資料庫連接器:將資料庫連接器【mysql-connector-java-5.1.10-bin.jar】放在Jboss的伺服器函式庫資料夾,如【jboss\server\default\lib】
  2. 資料庫連線設定:連線設定檔是用xml定義的,可直接複製JBoss提供的範本(位於【jboss\docs\examples\jca\mysql-ds.xml】)到【jboss\server\default\deploy】,並將資料庫設為你的MySQL連線設定。(如果用其他資料庫的話,在範本資料夾裡大都有範例)
    這邊比較需要注意的是等下要用到的名稱
    • jndi-name:等下設定驗證方式時會用到的名稱,例如下面範例的【MySqlDS】
    <?xml version="1.0" encoding="UTF-8"?>

    <!-- See http://www.jboss.org/community/wiki/Multiple1PC for information about local-tx-datasource -->
    <!-- $Id: mysql-ds.xml 88948 2009-05-15 14:09:08Z jesper.pedersen $ -->
    <!-- Datasource config for MySQL using 3.0.9 available from:
    http://www.mysql.com/downloads/api-jdbc-stable.html
    -->

    <datasources>
    <local-tx-datasource>
    <jndi-name>MySqlDS</jndi-name>
    <connection-url>jdbc:mysql://mysql-hostname:3306/jbossdb</connection-url>
    <driver-class>com.mysql.jdbc.Driver</driver-class>
    <user-name>x</user-name>
    <password>y</password>
    <exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter</exception-sorter-class-name>
    <!-- should only be used on drivers after 3.22.1 with "ping" support
    <valid-connection-checker-class-name>org.jboss.resource.adapter.jdbc.vendor.MySQLValidConnectionChecker</valid-connection-checker-class-name>
    -->
    <!-- sql to call when connection is created
    <new-connection-sql>some arbitrary sql</new-connection-sql>
    -->
    <!-- sql to call on an existing pooled connection when it is obtained from pool - MySQLValidConnectionChecker is preferred for newer drivers
    <check-valid-connection-sql>some arbitrary sql</check-valid-connection-sql>
    -->

    <!-- corresponding type-mapping in the standardjbosscmp-jdbc.xml (optional) -->
    <metadata>
    <type-mapping>mySQL</type-mapping>
    </metadata>
    </local-tx-datasource>
    </datasources>


    另外,如果覺得連線密碼這樣寫明碼太危險,可參考JBoss community的文件加密儲存
  3. 驗證方式設定:在JBoss的設定目錄下【jboss\server\default\conf】,有個【login-config.xml】,這個就是設定帳號驗證的方式(如果沒有這個檔也可以自己新增)
    裡面的參數
    • UserAA: 我設定的驗證來源名稱,這個在專案中會做對應的設定。
    • dsJndiName: 這邊就會對應到上一個設定的資料庫來源名稱MySqlDS
    • principalsQuery:這邊要寫查詢帳號密碼的SQL
    • rolesQuery:這邊要寫使用者角色的查詢SQL,角色會關係到後面網站權限的設定,第一個資料【roleName】所查詢出來的值我們這邊假設可能會有admin與guest,第二個資料是群組,我目前也不清楚是做什麼的,先依據官方範例給固定文字
    <?xml version='1.0'?>
    <policy>
    <application-policy name="UserAA">
    <authentication>
    <login-module code="org.jboss.security.auth.spi.DatabaseServerLoginModule" flag = "required">
    <module-option name = "dsJndiName">java:/MySqlDS</module-option>
    <module-option name = "principalsQuery">SELECT passwd FROM userdb.usersTab where userID=?</module-option>
    <module-option name = "rolesQuery">SELECT roleName,'Roles' FROM userdb.userRolesTab where userID=?</module-option>
    </login-module>
    </authentication>
    </application-policy>
    </policy>

MySQL

以下使用SQL script建立所需的資料庫與資料表,我將同時產生兩個預設的帳號分別屬於不同的權限角色,以下比較需要注意的部份是
  • 主要用到的資料來源是UsersTab資料表中的兩個欄位userID、passwd,還有UserRolesTab的兩個欄位userID、roleName,這部份不知道是不是有型態限制或是長度限制的問題,我用別的規格下去可能就無法認證。
  • 往下的Trigger是可有可無的,是我建立還方便管理資料庫用的
  • 最下面的insert是預設帳號與角色資料的建立
    • boss/0000:角色為admin
    • test/0000:角色為guest
CREATE DATABASE  IF NOT EXISTS `userdb` /*!40100 DEFAULT CHARACTER SET utf8 */;


DROP TABLE IF EXISTS `userdb`.`UsersTab`;
CREATE TABLE `userdb`.`UsersTab` (
`userID` varchar(64) NOT NULL,
`passwd` varchar(64) NOT NULL,
`createtime` datetime DEFAULT NULL,
`updatetime` datetime DEFAULT NULL,
PRIMARY KEY (`userID`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;


DROP TABLE IF EXISTS `userdb`.`UserRolesTab`;
CREATE TABLE `userdb`.`UserRolesTab` (
`userID` varchar(64) NOT NULL,
`roleName` varchar(32) NOT NULL DEFAULT 'guest',
`createtime` datetime DEFAULT NULL,
PRIMARY KEY (`userID`,`roleName`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;


DELIMITER $$
drop TRIGGER IF EXISTS `userdb`.UsersTab_Insert$$
CREATE TRIGGER `userdb`.UsersTab_Insert BEFORE INSERT ON `userdb`.UsersTab FOR EACH ROW
BEGIN
if new.createtime is null then
Set new.createtime = now();
end if;
if new.updatetime is null then
Set new.updatetime = now();
end if;
END$$

drop TRIGGER IF EXISTS `userdb`.UsersTab_Update$$
CREATE TRIGGER `userdb`.UsersTab_Update BEFORE UPDATE ON `userdb`.UsersTab FOR EACH ROW
BEGIN
if new.updatetime is null or old.updatetime=new.updatetime then
Set new.updatetime = now();
end if;
END$$

drop TRIGGER IF EXISTS `userdb`.UsersTab_Delete$$
CREATE TRIGGER `userdb`.UsersTab_Delete AFTER DELETE ON `userdb`.UsersTab FOR EACH ROW
BEGIN
delete from `userdb`.UserRolesTab where userID=old.userID;
END$$

drop TRIGGER IF EXISTS `userdb`.UserRolesTab_Insert$$
CREATE TRIGGER `userdb`.UserRolesTab_Insert BEFORE INSERT ON `userdb`.UserRolesTab FOR EACH ROW
BEGIN
if new.createtime is null then
Set new.createtime = now();
end if;
END$$
DELIMITER ;

insert into userdb.UsersTab (userID,passwd) values('boss','0000');
insert into userdb.UserRolesTab (userID,roleName) values('boss','admin');

insert into userdb.UsersTab (userID,passwd) values('test','0000');
insert into userdb.UserRolesTab (userID,roleName) values('test','guest');

Dynmic Web Project

動態網站的設定主要是在【WEB-INF】資料夾中新增一個【jboss-web.xml】,內容如下
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE jboss-web PUBLIC "-//JBoss//DTD Web Application 2.3V2//EN" "http://www.jboss.org/j2ee/dtd/jboss-web_3_2.dtd">

<jboss-web>
<security-domain>java:/jaas/UserAA</security-domain>
</jboss-web>
然後修改【web.xml】。這邊我採用Form認證的方式,也就是用網頁提供Login的介面。
  • security-constraint:這一段是設定哪些路徑可由哪些Role來存取,也就是權限設定。這部份有用到的角色一定要在下面的【security-role】有定義到。另外如果想設定成只有有登入的人才能存取,可將【role-name】設定成【*】。
  • login-config:這一段就是定義Login的方式與參照頁面(另依種方式設定為BASIC)
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
...
<security-constraint>
<web-resource-collection>
<web-resource-name></web-resource-name>
<url-pattern>/test/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
</auth-constraint>
</security-constraint>
<security-constraint>
<web-resource-collection>
<web-resource-name></web-resource-name>
<url-pattern>/Login</url-pattern>
<url-pattern>/Logout</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>*</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>FORM</auth-method>
<realm-name></realm-name>
<form-login-config>
<form-login-page>/login.jsp</form-login-page>
<form-error-page>/login.jsp?msg=Incorrect</form-error-page>
</form-login-config>
</login-config>
<security-role>
<role-name>admin</role-name>
</security-role>
<security-role>
<role-name>guest</role-name>
</security-role>
...
</web-app>

JSP & Servlet

再來我針對登入部份的網頁進行開發,主要會建立JSP:login.jsp與Servlet:Login、Logout。
實際上真正的登入網頁會是login.jsp,但因為如果使用者直接輸入login.jsp的網址後,進行登入成功後系統會不知該導到哪一頁(似乎也沒辦法設定預設導頁,網路上是有另一種作法如果有需要可自行參考)。
我這邊是自己想了個比較簡單的邏輯性解法,就是做一個Login的Servlet裡面直接會跳到首頁作為預設網頁,
然後將這個Login servlet設定必須登入才能存取(也就是上一步的web.xml中設定的),讓登入的連結以這個Servlet為主就會自動導自login.jsp。
login.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Login</title>
</head>
<body>

<h2 align="center">Login</h2>
<table border="0" align="center">
<tr>
<td>
<form method="POST" action="j_security_check">
<div>User ID :
<input type="text"
name="j_username">
</div>
<div>Password :
<input type="password"
name="j_password">
</div>
<div><input type="submit" value="Log In"></div>

<div style="color: red;"><%=(request.getParameter("msg")!=null)?request.getParameter("msg"):"" %></div>

</form>
</td>
</tr>
</table>

</body>
</html>
Login servlet
package view;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
* Servlet implementation class Login
*/
public class Login extends HttpServlet {
private static final long serialVersionUID = 1L;

/**
* @see HttpServlet#HttpServlet()
*/
public Login() {
super();
// TODO Auto-generated constructor stub
}

/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.sendRedirect(request.getContextPath() + "/index.jsp");
}
}

Logout servlet
package view;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


public class Logout extends HttpServlet {
private static final long serialVersionUID = 1L;

/**
* @see HttpServlet#HttpServlet()
*/
public Logout() {
super();
}

protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getSession().invalidate();
response.sendRedirect(request.getContextPath() + "/");
}
}

總結

以上設定完成後,就可以進到你的應用程式,然後存取Login servlet看看能不能正常登入登出了。
在這邊補充一些資訊,如果要在程式中取得登入者後的帳號,可以用【request.getUserPrincipal()】來取得Principal物件,如果不是null就可以呼叫該物件的getName()方法。
不過我個人比較喜歡用另外一個物件【org.jboss.security.SecurityAssociation】中的【getPrincipal()】也可以。
如果是要判斷使用者的角色,可使用【request.isUserInRole("admin")】方法來知道該使用者是否屬於admin這個角色。

參考資料

[程式]VB.Net2.0資料庫通用存取函式

序言

在VS2005建立VB專案(或Web網站)後,若要進行資料庫存取,我個人比較習慣將連線字串寫在設定檔app.config(或web.config)下。

不過VB專案預設是不會產生這個檔,而且在程式中若要取得連線字串的設定也要對專案的參考進行設定。

以下記錄下我做的設定,並把資料庫存取程式簡化為函式。

開發環境

  • VB.Net 2.0 (VS2005)
  • MSSQL2005 Express

專案設定

  • 建立專案後預設的專案屬性下,參考的元件如下圖:

  • 下面的程式中會用到【ConfigurationManager】這個物件來取得設定檔的連線字串,所以我們需要加入【System.Configuration】這個元件:

    點選加入,在.Net分頁下找到【System.Configuration】這個元件
  • 再來要在專案加入新項目【應用程式組態】,名稱用預設的【app.config】就可以了:

  • 編輯app.config,在【configuration】標籤內加入連線字串的設定如:

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
    ...
    <connectionStrings>
    <add name="MSSQLDB1"
    connectionString="Data Source=localhost;Initial Catalog=MyTestDB;Integrated Security=True"
    providerName="System.Data.SqlClient" />
    <add name="MSSQLDB2"
    connectionString="Data Source=127.0.0.1;Initial Catalog=MyTestDB;User ID=sa;Password=1234"
    providerName="System.Data.SqlClient" />
    </connectionStrings>
    ...

通用存取函式類別


Imports System.Data.SqlClient
Imports System.Configuration
Public Class DBAccessFunc
    ''' <summary>
    ''' 從ConfigurationManager中的ConnectionStrings找出Initial Catalog
    ''' </summary>
    ''' <param name="ConnName">ConnectionStrings名稱(String)</param>
    ''' <returns>回傳資料庫名稱</returns>
    ''' <remarks>從ConfigurationManager中的ConnectionStrings找出Initial Catalog</remarks>
    Public Shared Function getDBName(ByVal ConnName As String) As String
        Dim val As String = ""
        Dim ConnString As String = ConfigurationManager.ConnectionStrings(ConnName).ConnectionString
        Dim i As Integer = ConnString.IndexOf("Initial Catalog=")
        If i > -1 Then
            val = ConnString.Substring(i + "Initial Catalog=".Length)
            i = val.IndexOf(";")
            If i > -1 Then
                val = val.Substring(0, i)
            End If
        End If
        Return val
    End Function

    Public Shared Function getConnString(ByVal ConnName As String) As String
        Return ConfigurationManager.ConnectionStrings(ConnName).ConnectionString
    End Function


    Public Shared Function getConn(ByVal ConnName As String) As SqlConnection
        Return New SqlConnection(getConnString(ConnName))
    End Function
    ''' <summary>
    ''' 查詢資料庫
    ''' </summary>
    ''' <param name="cn">連線</param>
    ''' <param name="sql">查詢內容</param>
    ''' <returns>回傳查詢結果的DataTable</returns>
    ''' <remarks>查詢資料庫並回傳查詢結果的DataTable</remarks>
    Public Shared Function getTable(ByRef cn As SqlConnection, ByRef sql As String, Optional ByVal isColseConn As Boolean = True) As Data.DataTable
        Dim da As New SqlDataAdapter(sql, cn)
        Dim dt As New Data.DataTable("dt_xml")
        Try
            If cn.State = ConnectionState.Closed Then cn.Open()
            da.SelectCommand.CommandTimeout = 36000000
            da.Fill(dt)
        Catch ex As Exception
            If isColseConn And cn.State = ConnectionState.Open Then cn.Close()
            Throw ex
        End Try
        If isColseConn And cn.State = ConnectionState.Open Then cn.Close()
        Return dt
    End Function

    ''' <summary>
    ''' 執行命令
    ''' </summary>
    ''' <param name="cn">連線</param>
    ''' <param name="sql">查詢內容</param>
    ''' <returns>回傳受影響的資料筆數</returns>
    ''' <remarks>執行命令並回傳受影響的資料筆數</remarks>
    Public Shared Function doCmd(ByRef cn As SqlConnection, ByRef sql As String, Optional ByRef param() As SqlParameter = Nothing, Optional ByVal isColseConn As Boolean = True) As Integer
        Dim result As Integer = 0
        Dim cmd As New SqlCommand
        Try
            cmd.Connection = cn
            cmd.CommandText = sql
            If Not param Is Nothing Then
                cmd.Parameters.AddRange(param)
            End If
            cmd.CommandTimeout = 36000000
            If cn.State = ConnectionState.Closed Then cn.Open()
            result = cmd.ExecuteNonQuery()
        Catch ex As Exception
            cmd.Parameters.Clear()
            If isColseConn And cn.State = ConnectionState.Open Then cn.Close()
            Throw ex
        Finally
            cmd.Parameters.Clear()
            If isColseConn And cn.State = ConnectionState.Open Then cn.Close()
        End Try
        Return result
    End Function


    ''' <summary>
    ''' 取得單一資料
    ''' </summary>
    ''' <param name="cn">連線</param>
    ''' <param name="sql">查詢內容</param>
    ''' <returns>回傳受影響的資料筆數</returns>
    ''' <remarks>執行命令並回傳受影響的資料筆數</remarks>
    Public Shared Function doScalar(ByRef cn As SqlConnection, ByRef sql As String, Optional ByRef param() As SqlParameter = Nothing, Optional ByVal isColseConn As Boolean = True) As Object
        Dim result As Object = Nothing
        Dim cmd As New SqlCommand
        Try
            cmd.Connection = cn
            cmd.CommandText = sql
            If Not param Is Nothing Then
                cmd.Parameters.AddRange(param)
            End If
            cmd.CommandTimeout = 36000000
            If cn.State = ConnectionState.Closed Then cn.Open()
            result = cmd.ExecuteScalar()
        Catch ex As Exception
            cmd.Parameters.Clear()
            If isColseConn And cn.State = ConnectionState.Open Then cn.Close()
            Throw ex
        Finally
            cmd.Parameters.Clear()
            If isColseConn And cn.State = ConnectionState.Open Then cn.Close()
        End Try
        Return result
    End Function

    Public Function executeStoredProcedure(ByRef cn As SqlConnection, ByVal procedure As String, Optional ByRef param As SqlParameter() = Nothing, Optional ByRef output As SqlParameter() = Nothing, Optional ByVal isColseConn As Boolean = True) As Integer
        Dim result As Integer = 0
        Dim cmd As New SqlCommand(procedure, cn)
        Try

            cmd.CommandText = procedure
            cmd.CommandTimeout = 36000000
            cmd.CommandType = CommandType.StoredProcedure
            If Not param Is Nothing Then cmd.Parameters.AddRange(param)
            If Not output Is Nothing Then
                For Each o As SqlParameter In output
                    o.Direction = ParameterDirection.Output
                Next
                cmd.Parameters.AddRange(output)
            End If

            '開啟資料庫連線
            If cn.State = ConnectionState.Closed Then cn.Open()
            '設定變數儲存受影響資料列
            result = cmd.ExecuteNonQuery()
        Catch ex As Exception
            cmd.Parameters.Clear()
            If isColseConn And cn.State = ConnectionState.Open Then cn.Close()
            Throw ex
        Finally
            cmd.Parameters.Clear()
            If isColseConn And cn.State = ConnectionState.Open Then cn.Close()
        End Try
        Return result
    End Function
End Class


使用範例程式

Dim connStr1 As String = DBGenFunc.getConnStr("MSSQLDB1")
Dim sourceTable As String() = {"[" & DBGenFunc.getDBName("MSSQLDB1") & "].[dbo].[" & "MyTestTab" & "]", _
"[" & DBGenFunc.getDBName("MSSQLDB1") & "].[dbo].[" & "MyContentTab" & "]"}
Dim param() As SqlClient.SqlParameter = {New SqlClient.SqlParameter("P0", SqlDbType.VarChar)}
Dim sql As String

Dim title As String

Console.WriteLine("doCmdScalar Start:")
sql = "SELECT Title" & vbCrLf & _
" FROM " & sourceTable(0) & "" & vbCrLf & _
" WHERE SN=@P0"
param(0).Value = 1
title = DBGenFunc.doCmdScalar(connStr1, sql, param)
Console.WriteLine("doCmdScalar" & vbTab & title)

Console.WriteLine("getTable Start:")
sql = "SELECT Title" & vbCrLf & _
" FROM " & sourceTable(0) & "" & vbCrLf
Dim dt As DataTable = DBGenFunc.getTable(connStr1, sql)
For Each r As DataRow In dt.Rows
title = r.Item(0)
Console.WriteLine("getTable" & vbTab & title)
Next

Console.WriteLine("getTableToArray Start:")
Dim data As String() = DBGenFunc.dataTableToArray(Of String)(dt, 0)
For Each r As String In data
title = r
Console.WriteLine("getTable" & vbTab & title)
Next

Console.WriteLine("doCmd Start:")
sql = "INSERT INTO " & sourceTable(0) & "" & vbCrLf & _
"VALUES(@P0,@P1)"
param = New SqlClient.SqlParameter() {New SqlClient.SqlParameter("P0", SqlDbType.VarChar), _
New SqlClient.SqlParameter("P1", SqlDbType.VarChar)}
param(0).Value = "TNew"
param(1).Value = "SNew"
title = DBGenFunc.doCmd(connStr1, sql, param)
Console.WriteLine("doCmd" & vbTab & title)

Console.WriteLine("getReader Start:")
sql = "SELECT Title, Subject" & vbCrLf & _
" FROM " & sourceTable(0) & "" & vbCrLf
Dim dr As SqlClient.SqlDataReader = DBGenFunc.getReader(connStr1, sql)
While dr.Read()
title = dr.Item(0)
Console.WriteLine("getReader" & vbTab & title & vbTab & dr.Item(1))
End While
DBGenFunc.closeReader()

執行結果

doCmdScalar Start:
doCmdScalar T1
getTable Start:
getTable T1
getTable T2
getTable T3
getTable TNew
getTableToArray Start:
getTable T1
getTable T2
getTable T3
getTable TNew
doCmd Start:
doCmd 1
getReader Start:
getReader T1 S1
getReader T2 S2
getReader T3 S3
getReader TNew SNew
getReader TNew SNew

這裡是關於技術的手札~

也歡迎大家到

倫與貓的足跡



到噗浪來

關心一下我唷!
by 倫
 
Copyright 2009 倫倫3號Beta-Log All rights reserved.
Blogger Templates created by Deluxe Templates
Wordpress Theme by EZwpthemes