简单的C++ ORM设计

Posted 岬淢箫声

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了简单的C++ ORM设计相关的知识,希望对你有一定的参考价值。

注:本文是由社区的BOT Man写的,由我代为发上来。

2016/11/15

“没有好的接口,用C++读写数据库和写图形界面一样痛苦”

阅读这篇文章前,你最好知道什么是
Object Relation Mapping (ORM)

为什么C++要ORM

As good object-oriented developers got tired of this repetitive work,
their typical tendency towards enlightened laziness started
to manifest itself in the creation of tools to help automate
the process.

When working with relational databases,
the culmination of such efforts were object/relational mapping tools.

  • 一般的C++数据库接口,都需要手动生成SQL语句;
  • 手动生成的查询字符串,常常会因为模型改动而失效 (这里超级容易出错);
  • 查询语句/结果和C++原生数据之间的转换,每次都要手动解析;

市场上的C++ ORM

ODB

需要一个独立的 预编译器 生成模型和操作;

sqlpp11

使用  生成模型和操作,使用起来也比较复杂;
不过个人比较喜欢这个设计;

Hiberlite ORM

  • 需要在定义模型时,插入 额外的代码 进行注入;
  • 没有条件查询
    Transaction

C++的ORM要做什么

  • 将对C++对象操作转化成SQL查询语句
    (LINQ to SQL);
  • 提供C++ Style接口,更方便的使用;

一个可行的设计

一个实现了基本功能的C++ ORM —— ORM Lite

关于这个设计的代码和样例:

https://github.com/BOT-Man-JL/ORM-Lite

设计上大致分为6个方面:

  1. 封装SQL链接器
  2. 遍历对象内需要持久化的成员
  3. 序列化和反序列化
  4. 获取类名和各个字段的字符串
  5. 获取字段类型
  6. 将对C++对象的操作转化为SQL语句

1. 封装SQL链接器

为了让ORM支持各种数据库,
我们应该把对数据库的操作抽象为一个统一的 Execute

1 2 3 4 5 6 class SQLConnector public :      SQLConnector ( const std :: string &connectionString ) ;      void Execute ( . . . ) ; ;

  • 因为SQLite比较简单,目前只实现了SQLite的版本;
  • mysql版本应该会在
    这里 维护。。。

2. 遍历对象内需要持久化的成员

2.1 使用 Visitor Pattern + Variadic Template 遍历

一开始,我想到的是使用
Visitor Pattern
组合
Variadic Template
进行成员的遍历;

首先,在模型处加入 __Accept 操作;
通过 VISITOR 接受不同的 Visitor 来实现特定功能;
并用 __VA_ARGS__ 传入需要持久化的成员列表

1 2 3 4 5 6 7 8 9 10 11 #define ORMAP(_MY_CLASS_, ...)                            \\ template < typename VISITOR >                                \\ void __Accept ( VISITOR &visitor )                            \\                                                          \\      visitor . Visit ( __VA_ARGS__ ) ;                            \\                                                          \\ template < typename VISITOR >                                \\ void __Accept ( VISITOR &visitor ) const                      \\                                                          \\      visitor . Visit ( __VA_ARGS__ ) ;                            \\

然后,针对不同功能,实现不同的 Visitor
再通过统一的 Visit 接口,接受模型变长数据成员参数;
例如 ReaderVisitor

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 class ReaderVisitor public :      // Data to Exchange      std :: vector < std :: string > serializedValues ;        template < typename . . . Args >      inline void Visit ( Args & . . . args )               _Visit ( args . . . ) ;        protected :      template < typename T , typename . . . Args >      inline void _Visit ( T &property , Args orm

你如何在 Node.js 中模拟 MySQL(没有 ORM)?

Atitit.ati orm的设计and架构总结 适用于java c# php版

WEB框架Django之ORM操作

44 MySQL & orm对象关系映射

MySQL和其他数据库中的动态ORM?

(c)2006-2024 SYSTEM All Rights Reserved IT常识