学习实践:使用模式,原则实现一个C++数据库访问类
/** @brief 数据库操作异常 */
class HI_DB_EXPORT HiDBException
{
public:
HiDBException();
public:
std::string ToSrting();
public:
std::string m_sql; /**< 本次操作的SQL语句 */
std::string m_descript; /**< 异常描述 */
std::string m_position; /**< 异常位置 */
long m_errorId; /**< 异常编号 */
HiDBType m_dbTyp; /**< 数据库类型 */
};
/** @brief 异常语句宏 */
#define HiDBHelperOnError(ps, script,sql, id) \
HiDBException exception;\
exception.m_position = ps;\
exception.m_descript = script;\
exception.m_sql = sql;\
exception.m_errorId = id;\
throw exception;\
//return false;
/** @brief 数据库类型 */
enum HiDBType
{
HiDBType_Invail, /**< 无效类型 */
HiDBType_MySQL, /**< MySQL */
}; 构造函数的声明就明确下来了: /**
* @brief 构造函数
* @param[in] type 数据库类型
* @param[in] isUsingLock 是否需要使用互斥锁
*/
HiDB(HiDBType type = HiDBType_MySQL, bool isUsingLock = false); <>打开数据库连接
打开数据库连接比较简单: /**
* @brief 打开数据库连接
* @param[in] conn 数据库连接字符串
* @retval true:成功,false;失败
* @par 实例:
* @code
* HiDB db;
* if (db.Open("host=127.0.0.1;port=3306;dbname=test;user=root;pwd=root;charset=gbk;"))
* {
* // 打开成功
* }
* else
* {
* // 打开失败
* }
* @endcode
*/
bool Open(const char* conn) throw (HiDBException);
/**
* @brief 关闭据库连接
*/
void Close(void);
/**
* @brief 数据库连接是否打开
*/
bool IsOpen();
/**
* @brief 执行SQL语句,并不返回结果
* @param[in] conn SQL语句
* @retval true:成功,false;失败
* @par 实例:
* @code
* HiDB db;
* if (db.ExecuteNoQuery("UPDATE table SET Paramer1='%s'
* and Paramer2='%s' OR Paramer3=%d", "test1", "test2", 3))
* {
* // 执行成功
* }
* else
* {
* // 执行失败
* }
* @endcode
*/
bool ExecuteNoQuery(const char* sql, ...) throw (HiDBException);
/**
* @brief 执行SQL语句,返回一个结果
* @param[in] sql SQL语句
* @retval 获得的数据,如果为空,则失败
*/
std::string ExecuteScalar(const char* sql, ...) throw (HiDBException);
#ifndef HiDBTable typedef std::map<std::string, std::string> HiDBMap; /** @brief 查询结果 */
typedef std::vector<HiDBMap> HiDBTable; /**< 查询结果 */
#endif
/**
* @brief 执行SQL语句,返回一个结果集合
* @param[in] sql SQL语句
* @retval 存储查询记录的智能指针
*/
std::shared_ptr<HiDBTable> ExecuteQuery(const char* sql, ...) throw (HiDBException);
/**
* @brief 在事务中执行处理
* @param[in] fun 处理函数
*/
void OnTransaction(const std::function<void()>& fun) throw (HiDBException);
HiDB m_DB = new HiDB(HiDBType_MySQL, true);
try
{
bool ret = m_DB->Open(
"host=127.0.0.1;port=3306;dbname=test;user=root;pwd=root;charset=gbk;"
);
m_DB->ExecuteNoQuery("drop table if exists table1;");
string val = m_DB->ExecuteScalar(
"SELECT column4 FROM table1 WHERE column1='%s' AND column3=%d",
&val, "hitest", );
shared_ptr<HiDBTable> table = this->m_DB->ExecuteQuery(
"SELECT * FROM table1 WHERE column1='%s' OR column1='%s'",
"hitest", "mytest");
}
catch(HiDBException& e)
{
// ...
}
#pragma once /**
* @defgroup 数据库模块
* @{
*/
#include "HiDBExport.h" #include <string>
#include <vector>
#include <map>
#include <sstream> /** @brief 数据库类型 */
enum HiDBType
{
HiDBType_Invail, /**< 无效类型 */
HiDBType_MySQL, /**< MySQL */
}; #ifndef HiDBTable typedef std::map<std::string, std::string> HiDBMap; /** @brief 查询结果 */
typedef std::vector<HiDBMap> HiDBTable; /**< 查询结果 */
#endif /** @brief 数据库操作异常 */
class HI_DB_EXPORT HiDBException
{
public:
HiDBException();
public:
std::string ToSrting();
public:
std::string m_sql; /**< 本次操作的SQL语句 */
std::string m_descript; /**< 异常描述 */
std::string m_position; /**< 异常位置 */
long m_errorId; /**< 异常编号 */
HiDBType m_dbTyp; /**< 数据库类型 */
}; /** @brief 异常语句宏 */
#define HiDBHelperOnError(ps, script,sql, id) \
HiDBException exception;\
exception.m_position = ps;\
exception.m_descript = script;\
exception.m_sql = sql;\
exception.m_errorId = id;\
throw exception;\
//return false; /**//** @}*/ // 数据库模块
#pragma once /**
* @defgroup 数据库模块
* @{
*/ #include <memory>
#include <functional> #include "HiDBCommon.h" class HiDBImpl; #pragma warning (disable: 4290) /**
* @brief 数据库操作类,封装数据库的通用操作,本类使用策略模式实现
* @author 徐敏荣
* @date 2012-06-14
*
* @par 修订历史
* @version v0.5 \n
* @author 徐敏荣
* @date 2012-06-14
* @li 初始版本
* @version v0.6 \n
* @author 徐敏荣
* @date 2014-08-04
* @li 简化程序
*
*/
class HI_DB_EXPORT HiDB
{
public: /**
* @brief 构造函数
* @param[in] type 数据库类型
* @param[in] isUsingLock 是否需要使用互斥锁
*/
HiDB(HiDBType type = HiDBType_MySQL, bool isUsingLock = false); /**
* @brief 析构函数
*/
~HiDB(); public: /**
* @brief 打开数据库连接
* @param[in] conn 数据库连接字符串
* @retval true:成功,false;失败
* @par 实例:
* @code
* HiDB db;
* if (db.Open("host=127.0.0.1;port=3306;dbname=test;user=root;pwd=root;charset=gbk;"))
* {
* // 打开成功
* }
* else
* {
* // 打开失败
* }
* @endcode
*/
bool Open(const char* conn) throw (HiDBException); /**
* @brief 关闭据库连接
*/
void Close(void); /**
* @brief 数据库连接是否打开
*/
bool IsOpen(); public: /**
* @brief 执行SQL语句,并不返回结果
* @param[in] conn SQL语句
* @retval true:成功,false;失败
* @par 实例:
* @code
* HiDB db;
* if (db.ExecuteNoQuery("UPDATE table SET Paramer1='%s'
* and Paramer2='%s' OR Paramer3=%d", "test1", "test2", 3))
* {
* // 执行成功
* }
* else
* {
* // 执行失败
* }
* @endcode
*/
bool ExecuteNoQuery(const char* sql, ...) throw (HiDBException); public: /**
* @brief 执行SQL语句,返回一个结果
* @param[in] sql SQL语句
* @retval 获得的数据,如果为空,则失败
*/
std::string ExecuteScalar(const char* sql, ...) throw (HiDBException); public: /**
* @brief 执行SQL语句,返回一个结果集合
* @param[in] sql SQL语句
* @retval 存储查询记录的智能指针
*/
std::shared_ptr<HiDBTable> ExecuteQuery(const char* sql, ...) throw (HiDBException); public: /**
* @brief 在事务中执行处理
* @param[in] fun 处理函数
*/
void OnTransaction(const std::function<void()>& fun) throw (HiDBException); private:
/**
* @brief 数据库操作实现指针
*/
HiDBImpl* m_Impl; /**< 数据库操作实现指针 */
}; /**//** @}*/ // 数据库模块
#if !defined(HISDB_ON_VARLIST)
#define HISDB_ON_VARLIST(x, y) \
char chArr[] = {};\
char* pchar = &chArr[];\
va_list pArgList;\
va_start(pArgList, y);\
::_vsnprintf(chArr, , x, pArgList); \
va_end(pArgList) ;
#endif
/**
* @brief 临界区访问类,主要封装windows临界区的访问,该类主要在栈中使用,利用局部变量的构造和析构函数出入临界区
* @author 徐敏荣
* @date 2012-06-14
*
* @par 修订历史
* @version v0.5 \n
* @author 徐敏荣
* @date 2012-06-14
* @li 初始版本
*
*/
class HiCritical
{
public: /**
* @brief 构造函数
*/
HiCritical()
{
::InitializeCriticalSection(&cs);
} /**
* @brief 析构函数
*/
~HiCritical()
{
::DeleteCriticalSection(&cs);
} /**
* @brief 进入临界区
*/
void Enter()
{
::EnterCriticalSection(&cs);
} /**
* @brief 离开临界区
*/
void Leave()
{
::LeaveCriticalSection(&cs);
} CRITICAL_SECTION* GetSection()
{
return &cs;
}
private: /**
* @brief 临界区对象
*/
CRITICAL_SECTION cs; /**< 临界区对象 */
};
/**
* @brief 临界区访问管理类,利用构造函数进入临界区,利用西沟函数离开临界区
* 如果向构造函数提供NULL参数,则不使用临界区。
*
*/
class HiCriticalMng
{
public:
HiCriticalMng(HiCritical& crl): cl(&crl)
{
cl->Enter();
} HiCriticalMng(HiCritical* crl): cl(crl)
{
if (cl)
{
cl->Enter();
}
} ~HiCriticalMng()
{
if (cl)
{
cl->Leave();
}
} private:
HiCritical* cl;
};
#pragma once
/**
* @defgroup 数据库操作实现类接口类
* @brief 数据库操作实现类接口类,声明数据库操作实现类的接口。
* @author 徐敏荣
* @date 2012-06-14
*
* @par 修订历史
* @version v0.5 \n
* @author 徐敏荣
* @date 2012-06-14
* @li 初始版本
* @{
*/ #include "DB/HiDB.h"
class HiCritical;
/**
* @brief 数据库操作实现类接口类,声明数据库操作实现类的接口
*
*/
class HiDBImpl
{
public: /**
* @brief 构造函数
* @param[in] isUsingLock 是否需要使用互斥锁
*/
HiDBImpl(bool isUsingLock); /**
* @brief 析构函数
*/
virtual ~HiDBImpl(); public: /**
* @brief 打开数据库连接
* @param[in] conn 数据库连接字符串
* @retval true:成功,false;失败
*/
virtual bool Open(const char* conn) = ; /**
* @brief 关闭据库连接
*/
virtual void Close(void) = ; public: /**
* @brief 执行SQL语句,并不返回结果
* @param[in] conn SQL语句
* @retval true:成功,false;失败
*/
virtual bool ExecuteNoQuery(const char* sql) = ; public: /**
* @brief 执行SQL语句,返回一个结果
* @param[in] sql SQL语句
* @param[out] value 取得的结果
* @retval true:成功,false;失败
*/
virtual std::string ExecuteScalar(const char* sql) = ;
public: /**
* @brief 执行SQL语句,返回一个结果集合
* @param[in] sql SQL语句
* @param[out] table 取得的结果集合
* @retval true:成功,false;失败
*/
virtual std::shared_ptr<HiDBTable> ExecuteQuery(const char* sql) = ; public: /**
* @brief 事物处理
* @retval true:成功,false;失败
*/
virtual void OnTransaction(const std::function<void()>& fun) = ; protected: /**
* @brief 临界区对象,为空表示不需要考虑资源并发访问
*/
HiCritical* m_pCritical;
}; /**//** @}*/ // 数据库操作实现类接口类
#include <stdarg.h>
#include "DB/HiDB.h"
#include "HiDBMySQL.h" using namespace std; #if !defined(HISDB_ON_VARLIST)
#define HISDB_ON_VARLIST(x, y) \
char chArr[] = {};\
char* pchar = &chArr[];\
va_list pArgList;\
va_start(pArgList, y);\
::_vsnprintf(chArr, , x, pArgList); \
va_end(pArgList) ;
#endif static bool IsImplOK(HiDBImpl* db)
{
if (!db)
{
return false;
}
/*
if (!db->IsOpen())
{
return false;
}*/
return true;
} // 构造函数
HiDB::HiDB(HiDBType type, bool isUsingLock):m_Impl(NULL)
{
if (type == HiDBType_MySQL)
{
this->m_Impl = new HiDBMySQL(isUsingLock);
}
} // 析构函数
HiDB::~HiDB()
{
if (this->m_Impl)
{
delete this->m_Impl;
this->m_Impl = NULL;
}
} // 打开数据库连接
bool HiDB::Open(const char* conn)
{
if (!this->m_Impl)
{
return false;
} return this->m_Impl->Open(conn);
} bool HiDB::IsOpen()
{
if (!this->m_Impl)
{
return false;
} return true;//this->m_Impl->IsOpen();
} void HiDB::Close(void)
{
if (!IsImplOK(this->m_Impl))
{
return;
} return this->m_Impl->Close();
} bool HiDB::ExecuteNoQuery(const char* sql, ...)
{
if (!IsImplOK(this->m_Impl))
{
return false;
} HISDB_ON_VARLIST(sql, sql); return this->m_Impl->ExecuteNoQuery(chArr);
} string HiDB::ExecuteScalar(const char* sql, ...)
{
if (!IsImplOK(this->m_Impl))
{
return "";
} HISDB_ON_VARLIST(sql, sql); return this->m_Impl->ExecuteScalar(chArr);
} std::shared_ptr<HiDBTable> HiDB::ExecuteQuery(const char* sql, ...)
{
if (!IsImplOK(this->m_Impl))
{
return NULL;
}
HISDB_ON_VARLIST(sql, sql); return this->m_Impl->ExecuteQuery(chArr);
} void HiDB::OnTransaction(const std::function<void()>& fun)
{
if (!IsImplOK(this->m_Impl))
{
HiDBHelperOnError("HiDB::OnTransaction",
"HiDB is not impl", "", );
}
return this->m_Impl->OnTransaction(fun);
}
学习实践:使用模式,原则实现一个C++数据库访问类的更多相关文章
- 一个通用数据库访问类(C#,SqlClient)
本文转自:http://www.7139.com/jsxy/cxsj/c/200607/114291.html使用ADO.NET时,每次数据库操作都要设置connection属性.建立connecti ...
- 学习实践:使用模式,原则实现一个C++数据库訪问类
一.概述 在我參与的多个项目中.大家使用libMySQL操作MySQL数据库,并且是源代码级复用,在多个项目中同样或相似的源代码.这种复用方式给开发带来了不便. libMySQL的使用比較麻烦.非常e ...
- 一个C#的XML数据库访问类
原文地址:http://hankjin.blog.163.com/blog/static/33731937200942915452244/ 程序中不可避免的要用到配置文件或数据,对于数据量比较小的程序 ...
- [node.js学习]为node.js写的一个操作mysql的类
不支持一个对象在不同异步中使用,模仿的php框架 speedphp中的model模块 GaryMysql.js var mysql = require('mysql'); var pool = nul ...
- C++实现一个单例模板类
单例模式在项目开发中使用得比较多,一个单例的模板类显得很有必要,避免每次都要重复定义一个单例类型 //非多线程模式下的一个单例模板类的实现 // template_singleton.h #inclu ...
- 学习实践:使用模式,原则实现一个C++自动化测试程序
个人编程中比较喜欢重构,重构能够提高自己的代码质量,使代码阅读起来也更清晰.但是重构有一个问题,就是如何保证重构后带代码实现的功能与重构前的一致,如果每次重构完成后,对此不闻不问,则会有极大的风险,如 ...
- DRY原则的一个简单实践
转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 原文出处:https://dzone.com/articles/dry-dont-repeat-yourse ...
- 编码最佳实践——Liskov替换原则
Liskov替换原则(Liskov Substitution Principle)是一组用于创建继承层次结构的指导原则.按照Liskov替换原则创建的继承层次结构中,客户端代码能够放心的使用它的任意类 ...
- 前端学习实践笔记--JavaScript深入【1】
这一年中零零散散看过几本javascript的书,回过头看之前写过的javascript学习笔记,未免有点汗颜,突出“肤浅”二字,然越深入越觉得javascript的博大精深,有种只缘身在此山中的感觉 ...
随机推荐
- MyBatis-Plus的一些问题
图一图二分别是搜索设计师的动态sql,已知这个字段是integer类型.为什么用=号查询的时候会显示查询超时.但是我把sql打印出来的结果直接去执行,时间在一秒是可以出来结果的. 但是用like一个i ...
- Leetcode题目48.旋转图像(中等)
题目描述: 给定一个 n × n 的二维矩阵表示一个图像. 将图像顺时针旋转 90 度. 说明: 你必须在原地旋转图像,这意味着你需要直接修改输入的二维矩阵.请不要使用另一个矩阵来旋转图像. 示例 1 ...
- (转载)完成端口(CompletionPort)详解 - 手把手教你玩转网络编程系列之三
转自:http://blog.csdn.net/piggyxp/article/details/6922277 前 言 本系列里完成端口的代码在两年前就已经写好了,但是由于许久没有写东西了,不知该如何 ...
- HearthBuddy中_settings.txt的更详细参数解释
https://tieba.baidu.com/p/5275382967 默认的配置不是很合理,花了点时间读了下silverfish(也就是兄弟用的AI)的代码后也尝试修改了些参数,有没有效果仁者见仁 ...
- ffmpe转码添加时间水印
ffmpeg出直播流的时候 添加时间水印的话可以观察延迟 录制也方便查问题下面的命令 需要用到的字体自己百度下载一下或者到C:\Windows\Fonts复制一下 ffmpeg -stream_loo ...
- 【Taro全实践】Taro在微信小程序中的生命周期
一.Taro的本身生命周期 生命周期componentWillMount在微信小程序中这一生命周期方法对应页面的onLoad或入口文件app中的onLaunch componentDidMount在微 ...
- 进程对列,生产者和消费者,JoinableQueue
1.进程对列 让进程之间共享资源 先进先出 (1)基本语法 from multiprocessing import Process,Queue q = Queue() # 1.用put方法往队列中存值 ...
- Swift的if let和guard let的使用 <一看就懂哟>
// // ViewController.swift // 可选项的判断 // // Created by 思 彭 on 16/9/16. // Copyright © 2016年 思 彭. All ...
- Jenkins+Ansible+Gitlab自动化部署三剑客
一.gitlab安装 环境:centos 7 x64 1.关闭防火墙 systemctl stop firewalld systemctl disable firewalld 2.禁用selinux ...
- How to remove duplicate lines in a large text file?
How would you remove duplicate lines from a file that is much too large to fit in memory? The dupli ...