一、简介

libDBConnector程序库使用C/C++语言开发,通过MySQL C API 和Oralce OCI方式访问MySQL和Oracle数据库,且程序库可以跨平台使用,保留统一访问接口,用户只需设置创建连接对象的参数,即可改变数据库连接,同时保证同一应用程序可同时访问MySQL和Oralce数据库,并可同时连接多个数据库。

二、程序架构

程序架构

三、功能说明

公共接口文件:

IDBConnect.h

#ifndef _DB_CONNECT_H_
#define _DB_CONNECT_H_
 
#include "IDBRecordSet.h"
 
#define EXPORT __declspec(dllexport)
 
enum DB_TYPE {_MYSQL_, _ORACLE_};
 
class IDBConnect
{
// Construction and Destruction
public:
	IDBConnect();
	virtual ~IDBConnect();
 
public:
	virtual bool Connect( const wchar *host, 
						  const wchar *user, 
						  const wchar *passwd, 
						  const wchar *db, 
						  const uint32 port) = 0;
	virtual void Close(void) = 0;
	virtual bool Execute(const wchar *sql) = 0;
	virtual bool StorBinData(const wchar *insertsql, const wchar *sql, const wchar *binfilename) = 0;
	virtual	bool ReadBinData(const wchar *binfilename) = 0;
 
	// connection status
	virtual bool IsOpen(void) = 0;
 
	// reserved
	//virtual int SetConnOptions(enum mysql_option option, const char *arg) = 0;
 
	// transaction
	virtual bool BeginTrans(void) = 0;
	virtual bool RollbackTrans(void) = 0;
	virtual bool CommitTrans(void) = 0;
	virtual bool EndTrans(void) = 0;
 
	virtual int GetLastError(void) = 0;
	virtual int GetRealString(const wchar *inbuffer, uint32 length, wchar *&outbuffer) = 0;
};
 
/* public interface function */
namespace wDBConnector
{
EXPORT    void SetDBType(DB_TYPE dbType);
EXPORT DB_TYPE GetDBType();
	
EXPORT IDBConnect*	 Create(DB_TYPE dbType);
EXPORT IDBRecordSet* Create(IDBConnect *pDBConn);
 
EXPORT void Destroy(IDBConnect *&pDBConn);
EXPORT void Destroy(IDBRecordSet *&pDBRs);
 
// 调用Connect函数前,一定要先执行SetDBType函数,
// 否则将启用默认数据库连接方式(ORACLE)
EXPORT IDBConnect * Connect(const wchar *host, 
		   					const wchar *user, 
						    const wchar *passwd, 
						    const wchar *db, 
						    const uint32 port);
 
// 适用于短连接,调用ExecSQL函数前,一定要先执行SetConnectParam函数
EXPORT void SetConnectParam(const wchar *host, 
							const wchar *user, 
							const wchar *passwd, 
							const wchar *db, 
							const uint32 port);
EXPORT bool ExecSQL(const wchar *sql);
 
EXPORT void Close(IDBConnect *&pDBConn);
EXPORT void Close(IDBRecordSet *&pDBRs);
}
 
#endif

IDBRecordSet.h

#ifndef _DB_RECORDSET_H_
#define _DB_RECORDSET_H_
 
#ifdef _UNICODE
typedef wchar_t wchar;
#else
typedef char wchar;
#endif
 
typedef unsigned __int64 uint64;
typedef unsigned int	 uint32;
typedef unsigned long    ulong;
 
enum FieldTypes { 
	TYPE_INT,
	TYPE_LONG,
	TYPE_FLOAT,
	TYPE_DOUBLE,
	TYPE_DATETIME,
	TYPE_ENUM,
	TYPE_SET,
	TYPE_STRING
};
 
class IDBRecordSet
{
public:
	IDBRecordSet();
	virtual ~IDBRecordSet();
 
public:
	virtual bool Query(const wchar *sql) = 0;
	virtual void Close(void) = 0;
	virtual bool Refresh(uint32 options) = 0;
 
	virtual wchar *GetFieldValue(const wchar *field) = 0;
	virtual wchar *GetFieldValue(const int index) = 0;
	virtual int    GetFieldValueInt(const wchar *field) = 0;
	virtual float  GetFieldValueFlt(const wchar *field) = 0;
	virtual double GetFieldValueDbl(const wchar *field) = 0;
	virtual void  *GetBinaryData(const wchar *field) = 0;
	
	virtual ulong  GetFieldsCount(void) = 0;
	virtual uint64 GetRecordCount(void) = 0;
	virtual ulong *GetColumnLength(void) = 0;
	virtual FieldTypes GetFieldType(const int index) const = 0;
	virtual FieldTypes GetFieldType(const wchar *field) = 0;
 
	virtual bool IsOpen(void) = 0;
	virtual bool IsBOF(void) = 0;
	virtual bool IsEOF(void) = 0;
	virtual bool IsFieldNull(const int index) = 0;
	virtual bool IsFieldNull(const wchar *field) = 0;
 
	// RecordSet Navigation
	virtual void MoveFirst(void) = 0;
	virtual void MoveLast(void) = 0;
	virtual void MoveNext(void) = 0;
	virtual void MovePrev(void) = 0;
};
 
#endif

四、历史版本

v1.0

  • 修正了当填入错误的连接参数进行数据库连接时,获取返回值需要很长时间的错误。
    • 涉及函数:Connect();

v1.1

  • 增加了Unicode支持
  • 改为命名域方式访问接口
  • 增加了存储二进制文件功能

五、ORACLE客户端配置说明

windows:

访问www.oracle.com网站,下载instantclient-basic-win32-11.2压缩包,解压到C:\根目录(其它目录亦可)下,重命名文件夹为instantclient。

下载instantclient-sqlplus-win32-11.2压缩包,解压到C:\instantclient(推荐)。

设置系统环境变量:

NLS_LANG=SIMPLIFIED CHINESE_CHINA.ZHS16GBK
TNS_ADMIN=C:\instantclient
Path=C:\instantclient

创建tnsnames.ora文件,拷贝到C:\instantclient目录下,文件内容如下:

ORCL =
   (DESCRIPTION =
     (ADDRESS_LIST =
       (ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521))
     )
     (CONNECT_DATA =
       (SERVICE_NAME = orcl)
     )

   )

Host填写目的数据库服务器IP地址,本例为localhost(本机数据库服务器)

linux:

第一步 执行命令:

rpm -ivh oracle-instantclient11.2-basic-11.2.0.2.0.i386.rpm
rpm -ivh oracle-instantclient11.2-sqlplus-11.2.0.2.0.i386.rpm

第二步 设置环境变量:

  • 进入root目录
  • ls -a 显示隐藏的.bashrc文件
  • Vim编辑.bashrc文件,增加如下内容:
export LD_LIBRARY_PATH=/usr/local/lib:/usr/lib/oracle/11.2/client/lib
export ORACLE_HOME=/usr/lib/oracle/11.2
export TNS_ADMIN=$ORACLE_HOME:/network/admin
NLS_LANG="Simplified Chinese_China.ZHS16GBK"

That’s OK.

第三步 测试连通性:

  • 打开命令终端
  • 输入sqlplus /nolog命令
  • 输入conn scott/tiger@orcl,如果出现“已连接”字样,则证明数据库客户端配置成功。

六、使用例程

步骤一:包含头文件

   #include "IDBConnect.h"

步骤二:创建连接对象指针

   // 输入参数:_ORACLE或_MYSQL_
   // 返回值:连接对象指针非空,则证明创建成功!
   IDBConnect *pDBConn = wDBConnector::Create(_ORACLE_);

步骤三:连接数据库

   // 输入参数:host -> tnsnames.ora中的连接字符串,例如:orcl_192.168.1.1
   //          user -> 用户名
   //          passwd -> 密码
   //          db     -> 数据库名称(若是连接ORACLE,可忽略此参数项)
   //          port   -> 数据库端口号
   // 
   // 返回值:true - 成功 false - 失败
   bool bRetValue = pDBConn->Connect(host, user, passwd, db, port);

步骤四:创建记录集对象指针

   // 输入参数:连接对象指针
   // 返回值:记录集对象指针非空,则证明创建成功!
   IDBRecordSet *pDBRs = wDBConnector::Create(pDBConn);

步骤五:执行SQL语句

   // 输入参数:SQL语句
   // 返回值:true - 成功 false - 失败
   bool bRetValue = pDBRs->Query(sql);

⚠️注意:连接ORACLE数据库时,SQL语句不能加分号结尾。

步骤六:获取结果集数据

   // 输入参数:数据表的字段名称
   // 返回值:某条记录字段的数据值
   char *pName = NULL;
   
   while (!pDBRs->IsEOF())
   {
       pName = pDBRs->GetFieldValue(Name);
       printf(%s\n, pName);
       pDBRs->MoveNext();
   }

步骤七:关闭记录集对象

   pDBRs->Close();

步骤八:关闭连接对象

   pDBConn->Close();

步骤九:销毁记录集对象指针

   wDBConnector::Destroy(pDBRs);

步骤十:销毁连接对象指针

   wDBConnector::Destroy(pDBConn);

⚠️注意:通常wDBConnector::Create和wDBConnector::Destroy是对应出现的,否则将发生内存泄露。

完整代码:

#include “IDBConnect.h”
#include <cassert>
#include <cstdio>
int main()
{
    IDBConnect *pDBConn = wDBConnector::Create(_ORACLE_);
    assert(NULL != pDBConn);
    if (NULL == pDBConn)
    {
        printf(Failed to Create Connection Object.\n)
        return 0;
    }
 
    const char *host   = 192.168.1.1;
    const char *user   = test;
    const char *passwd = test;
    const char *db     = db;
    const int  port    = 3306;
    bool bRetValue = pDBConn->Connect(host, user, passwd, db, port);
    if (!bRetValue)
    {
        wDBConnector::Destroy(pDBConn);
        return 0;
    }
 
    // create a recordset instance…
    IDBRecordSet *pDBRs = wDBConnector::Create(pDBConn);
    assert(NULL != pDBRs)
    if (NULL == pDBRs)
    {
        printf(Failed to Create Record Set Object.\n);
        wDBConnector::Destroy(pDBConn);
        return 0;
    }
    const char *sql = select * from table;
    bRetValue = pDBRs->Query(sql);
    if (!bRetValue)
    {
        printf(Failed to Query Data.\n);
        goto END;
    }
 
    char *pName = NULL;
    while (!pDBRs->IsEOF())
    {
        pName = pDBRs->GetFieldValue(Name);
        printf(%s\n, pName);
 
        pDBRs->MoveNext();
    }
 
END:
    pDBRs->Close();
    pDBConn->Close();
 
    wDBConnector::Destroy(pDBRs);
    wDBConnector::Destroy(pDBConn);
 
    return 0;
}