高性能服务器开发 -》需求实现5 数据库模块设计

下面我们可以开始设计数据库模块了

一个正常的服务器,多半是需要数据库功能的。 当时在C++环境下,好的数据库代码并不多

什么是好的数据库代码?

  1. 满足数据库的接入要求
  2. 使用方便简洁
  3. 自动化程度高
  4. 适配性广泛

这里我们将一起研究一下,如何实现一个好的数据库模块,方便我们的使用

需求说明

现在我们要搞清楚,数据库到底有哪些接入要求。 首先,我们需要有一个能灵活修改的数据结构,方便我们去适配数据库中各种表的内容 这意味着我们需要一个动态可调表类。

其次,我们需要表的创建、查询SQL语句自动化生成功能。 这样我们可以方便的处理表

最后,我们还需要一套数据库接口,提供数据库的连接、查询和结果的获取

当然,一些配套的功能也是不能少的。 比如数据库关闭,查询失败的处理等等。

这些需求中,最麻烦的是动态创建一个和表呼应的类,来方便进行数据库创建、存储和查询 这里面需要用到一些宏的技巧,和类的设计的技巧。 此外,还需要大量的辅助类,来记录列信息,表信息,结果信息等等。

而且数据库类应该是一个接口类,配合一些具体实现的类。 这样可以方便对接不同的数据库

依赖实现

​
class ValueTool {
		//判断是否存在toString
		template<typename U, String(U::*)()>struct HELP;
		template<typename U>static char Test(HELP<U, &U::toString>*);
		template<typename U>static int Test(...);
		//判断是否存在c_str
		template<typename U, const char* (U::*)() const>struct HELP1;
		template<typename U>static char Test1(HELP<U, &U::toString>*);
		template<typename U>static int Test1(...);
	public:
		const static bool has_toString = sizeof(Test<value>(0)) == sizeof(char);
		const static bool has_c_str = sizeof(Test1<Value>(0) == sizeof(char));
		static std::enable_if<has_toString,String>
			toString(const Value& v) {
			return v.toString();
		}

		static std::enable_if<has_c_str,String>
			toString(const Value& v) {
			return _T("\"") + v + _T("\"");
		}

		String toString(const char* v) {
			return _T("\"") + String(v) + _T("\"");
		}

		static std::enable_if<!has_toString && !has_c_str,String>
			toStriing(const Value& v) {
			StrStream s;
			s << v;
			return s.str();
		}
	};

​
using CParamIter = StrList::const_iterator;
	using ParamIter = StrList::iterator;

	struct StrListParam{
		template<typename ..._ARGS_>
		StrListParam(const _ARGS_&...args) {
			int _[] = { (Append(args),0)... };
		}
		StrListParam(const StrListParam& slp) {
			lstParams.insert(lstParams.end(), slp.lstParams.begin(), slp.lstParams.end());
		}
		StrListParam& operator=(const StrListParam& slp) {
			if (this != &slp) {
				lstParams.insert(lstParams.end(), slp.lstParams.begin(), slp.lstParams.end());
			}
			return *this;
		}
		CParamIter begin()const { return lstParams.begin(); }
		ParamIter begin() { return lstParams.begin(); }
		CParamIter end()const { return lstParams.end(); }
		ParamIter end() { return lstParams.end(); }
		size_t size() const { return lstParams.size(); }
		StrList lstParams;
	private:
		template<typename TAIL>
		void Append(const TAIL& tail) { lstParams.push_back(tail); }
	};
	using SLParam = struct StrListParam;


#define _V(X) ValueTool::toString((X))


	struct _Field_{
	public:
		virtual String Create();
		_Field_() { Attr = NONE; }
		_Field_(const _Field_& field);
		virtual ~_Field_() { Attr = NONE; }
		virtual _Field_& operator=(const _Field_& field);
		virtual void FromString(const String& sValue);
		virtual String toEqualExp()const = 0;
		String FullName()const;
		virtual String toString()const = 0;
	public:
		String Name;
		String Type;
		unsigned Attr;
		String Default;
		String Check;
	};

	template<typename T>
	class _DeclareField :public _Field_
	{
	public:
		_DeclareField() :_Field_() { value = T(); }
		_DeclareField(const _DeclareField& field) :_Field_(field) {
			value = field.value;
		}
		virtual ~_DeclareField() {}
		virtual _Field_& operator=(const _Field_& field) {
			if (this != &field) {
				_Field_::operator=(field);
				value = dynamic_cast<const _DeclareField<T>&>(field).value;
			}
			return *this;
		}
		virtual void FromString(const String& sValue) { _Field_::FromString(sValue); }
		T& Value() { return value; }
	public:
		T value;
	};

	template<>
	class _DeclareField<void> :public _Field_
	{
	public:
		_DeclareField() :_Field_() { value = nullptr; }
		_DeclareField(const _DeclareField& field) :_Field_(field) {
			value = nullptr;
		}
		virtual ~_DeclareField(){}
		virtual _DeclareField& operator=(const _DeclareField& field) {
			return *this;
		}
		virtual void FromString(const String& sValue) {}
		void* Value() { return value; }
	public:
		void* value;
	};

	using FieldArray = std::vector<std::shared_ptr<_Field_>>;
	using FieldMap = std::map<String, std::shared_ptr<_Field_>>;
	using FMapIter = FieldMap::iterator;
	using FMapCIter = FieldMap::const_iterator;
	using PField = std::shared_ptr<_Field_>;

	struct _Table_ {
	public:
		_Table_() {}
		_Table_(const _Table_& table) {
			Database = table.Database;
			Name = table.Name;
			Columns = table.Columns;
			Fields = table.Fields;
		}
		virtual String Create();
		virtual String Insert(const SLParam& Columns, const SLParam& Values);
		virtual String Drop();
		virtual String Modify(const  SLParam& Columns, const SLParam& Values);
		virtual String Query();
		virtual std::shared_ptr<_Table_>Copy()const = 0;
		String FullName()const;
	public:
		String Database;//表所属的库
		String Name;
		FieldArray Columns;
		FieldMap Fields;
	};

	using PTable = std::shared_ptr<_Table_>;
	using TableArray = std::vector<PTable>;
	using TableList = std::list<PTable>;

#define DECLARE_TABLE_CLAEE(name) \
class name:public _Table_{ \
public: \
virtual PTable Copy()const{return PTable(new name(*this));} \
name():_Table_(){Name=_T(#name);
	
#define DECLARE_ITEM(name,attr,type,size,Default,check) \
{PField field(new type(_T(#name),attr,_T(size),_T(Default),_T(check))); \
Columns.push_back(field); \
Fields.insert(std::pair<String,PField>(_T(#name),field));}
	
#define DECLARE_TABLE_CLASS_END()	}};

这里有两个类比较重要 _Field_ 、 _Table_

考虑到数据中,最重要的核心就是表,所以我们设计了表的基类_Table_

而表又是由若干列组成,所以我们设计了基类_field_

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

#A#

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值