{"id":15039377,"url":"https://github.com/qicosmos/ormpp","last_synced_at":"2025-05-14T12:12:27.483Z","repository":{"id":39817593,"uuid":"109477358","full_name":"qicosmos/ormpp","owner":"qicosmos","description":"modern C++ ORM, C++17, support mysql, postgresql,sqlite","archived":false,"fork":false,"pushed_at":"2025-05-08T03:06:06.000Z","size":4124,"stargazers_count":1378,"open_issues_count":29,"forks_count":288,"subscribers_count":57,"default_branch":"master","last_synced_at":"2025-05-08T04:19:36.836Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/qicosmos.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2017-11-04T07:57:11.000Z","updated_at":"2025-05-08T03:06:10.000Z","dependencies_parsed_at":"2023-02-16T03:46:08.752Z","dependency_job_id":"763e7626-6f28-446a-bb05-9691febe4710","html_url":"https://github.com/qicosmos/ormpp","commit_stats":{"total_commits":616,"total_committers":18,"mean_commits":34.22222222222222,"dds":0.3133116883116883,"last_synced_commit":"f3a59b944a9aed2f598425799f6cb413cd4ceeac"},"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/qicosmos%2Formpp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/qicosmos%2Formpp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/qicosmos%2Formpp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/qicosmos%2Formpp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/qicosmos","download_url":"https://codeload.github.com/qicosmos/ormpp/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254140768,"owners_count":22021220,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-09-24T20:42:36.704Z","updated_at":"2025-05-14T12:12:27.469Z","avatar_url":"https://github.com/qicosmos.png","language":"C++","readme":"\u003cp align=\"center\"\u003e\n\u003ca href=\"https://github.com/qicosmos/ormpp/actions/workflows/ci-sqlite.yml\"\u003e\n\u003cimg alt=\"ci-sqlite\" src=\"https://github.com/qicosmos/ormpp/actions/workflows/ci-sqlite.yml/badge.svg?branch=master\"\u003e\n\u003c/a\u003e\n\u003ca href=\"https://github.com/qicosmos/ormpp/actions/workflows/ci-mysql.yml\"\u003e\n\u003cimg alt=\"ci-mysql\" src=\"https://github.com/qicosmos/ormpp/actions/workflows/ci-mysql.yml/badge.svg?branch=master\"\u003e\n\u003c/a\u003e\n\u003ca href=\"https://github.com/qicosmos/ormpp/actions/workflows/ci-pgsql.yml\"\u003e\n\u003cimg alt=\"ci-pgsql\" src=\"https://github.com/qicosmos/ormpp/actions/workflows/ci-pgsql.yml/badge.svg?branch=master\"\u003e\n\u003c/a\u003e\n\u003ca href=\"https://codecov.io/gh/qicosmos/ormpp\"\u003e\n\u003cimg alt=\"codecov\" src=\"https://codecov.io/gh/qicosmos/ormpp/branch/master/graph/badge.svg\"\u003e\n\u003c/a\u003e\n\u003cimg alt=\"language\" src=\"https://img.shields.io/github/languages/top/qicosmos/ormpp?style=flat-square\"\u003e\n\u003cimg alt=\"last commit\" src=\"https://img.shields.io/github/last-commit/qicosmos/ormpp?style=flat-square\"\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/qicosmos/ormpp/tree/master/lang/english/README.md\"\u003eEnglish\u003c/a\u003e | \u003cspan\u003e中文\u003c/span\u003e\n\u003c/p\u003e\n\n# 一个很酷的Modern C++ ORM库----ormpp\n\niguana版本1.0.9\nhttps://github.com/qicosmos/iguana.git\n\n[谁在用ormpp](https://github.com/qicosmos/ormpp/wiki), 也希望ormpp用户帮助编辑用户列表，也是为了让更多用户把ormpp用起来，也是对ormpp 最大的支持，用户列表的用户问题会优先处理。\n\n## 目录\n\n* [ormpp的目标](#ormpp的目标)\n* [ormpp的特点](#ormpp的特点)\n* [快速示例](#快速示例)\n* [如何编译](#如何编译)\n* [接口介绍](#接口介绍)\n* [roadmap](#roadmap)\n* [联系方式](#联系方式)\n\n## ormpp的目标\normpp最重要的目标就是让c++中的数据库编程变得简单，为用户提供统一的接口，支持多种数据库，降低用户使用数据库的难度。\n\n## ormpp的特点\normpp是modern c++(c++11/14/17)开发的ORM库，目前支持了三种数据库：mysql, postgresql和sqlite，ormpp主要有以下几个特点：\n\n1. header only\n1. cross platform\n1. unified interface\n1. easy to use\n1. easy to change database\n\n你通过ormpp可以很容易地实现数据库的各种操作了，大部情况下甚至都不需要写sql语句。ormpp是基于编译期反射的，会帮你实现自动化的实体映射，你再也不用写对象到数据表相互赋值的繁琐易出错的代码了，更酷的是你可以很方便地切换数据库，如果需要从mysql切换到postgresql或sqlite只需要修改一下数据库类型就可以了，无需修改其他代码。\n\n## 自增主键\n\n使用REGISTER_AUTO_KEY注册自增主键\n\n```C++\nstruct person {\n  std::string name;\n  int age;\n  int id;\n};\nREGISTER_AUTO_KEY(person, id)\nYLT_REFL(person, id, name, age)\n```\n\n## 冲突主键\n\n使用REGISTER_CONFLICT_KEY注册冲突主键来进行update，如果未注册冲突主键则会采用自增主键\n\n```C++\nstruct student {\n  int code;\n  std::string name;\n  char sex;\n  int age;\n  double dm;\n  std::string classroom;\n};\nREGISTER_CONFLICT_KEY(student, code)\nYLT_REFL(student, code, name, sex, age, dm, classroom)\n```\n\n## 快速示例\n\n这个例子展示如何使用ormpp实现数据库的增删改查之类的操作，无需写sql语句。\n\n```C++\n#include \"dbng.hpp\"\n#include \"mysql.hpp\"//注意，使用什么数据库时就需要include对应的hpp文件，里面是对相关函数的反射封装\n//#include \"sqlite.hpp\" //例如使用sqlite时，则包含sqlite.hpp\nusing namespace ormpp;\n\nstruct person {\n  std::optional\u003cint\u003e age; // 可以插入null值\n  std::string name;\n  int id;\n  static constexpr auto get_alias_field_names(alias *) {\n    return std::array{ylt::reflection::field_alias_t{\"person_id\", 0},\n                      ylt::reflection::field_alias_t{\"person_name\", 1},\n                      ylt::reflection::field_alias_t{\"person_age\", 2}}; // 注意: 这里需与YLT_REFL的注册顺序一致\n  }\n  static constexpr std::string_view get_alias_struct_name(student *) {\n    return \"CUSTOM_TABLE_NAME\"; // 表名默认结构体名字(person), 这里可以修改表名\n  }\n};\nREGISTER_AUTO_KEY(person, id)\nREGISTER_CONFLICT_KEY(person, name)\n// REGISTER_CONFLICT_KEY(person, name, age) // 如果是多个\nYLT_REFL(person, id, name, age)\n\nint main() {\n  person p = {\"test1\", 2};\n  person p1 = {\"test2\", 3};\n  person p2 = {\"test3\", 4};\n  std::vector\u003cperson\u003e v{p1, p2};\n\n  dbng\u003cmysql\u003e mysql;\n  mysql.connect(\"127.0.0.1\", \"dbuser\", \"yourpwd\", \"testdb\");\n  mysql.create_datatable\u003cperson\u003e(ormpp_auto_key{\"id\"});\n\n  // 插入数据\n  mysql.insert(p);\n  mysql.insert(v);\n\n  // 查询数据(id=1)\n  auto result = mysql.query_s\u003cperson\u003e(\"id=?\", 1);\n\n  // 获取插入后的自增id\n  auto id1 = mysql.get_insert_id_after_insert\u003cperson\u003e(p);\n  auto id2 = mysql.get_insert_id_after_insert\u003cperson\u003e(v);\n\n  // 更新数据\n  mysql.update(p);\n  mysql.update(v);\n  mysql.update(p, \"id=1\");\n\n  // 替换数据\n  mysql.replace(p);\n  mysql.replace(v);\n\n  // 更新指定字段\n  // mysql.update_some\u003c\u0026person::name, \u0026person::age\u003e(p);\n  // mysql.update_some\u003c\u0026person::name, \u0026person::age\u003e(v);\n\n  auto result = mysql.query_s\u003cperson\u003e();\n  for (auto \u0026person : result) {\n    std::cout \u003c\u003c person.id \u003c\u003c \" \" \u003c\u003c person.name \u003c\u003c \" \" \u003c\u003c person.age\n              \u003c\u003c std::endl;\n  }\n\n  mysql.delete_records\u003cperson\u003e();\n\n  // transaction\n  mysql.begin();\n  for (int i = 0; i \u003c 10; ++i) {\n    person s = {\"tom\", 19};\n    if (!mysql.insert(s)) {\n      mysql.rollback();\n      return -1;\n    }\n  }\n  mysql.commit();\n  return 0;\n}\n```\n\n```C++\nenum class Color { BLUE = 10, RED = 15 };\nenum Fruit { APPLE, BANANA };\n\nstruct test_enum_t {\n  Color color;\n  Fruit fruit;\n  int id;\n};\nREGISTER_AUTO_KEY(test_enum_t, id)\nYLT_REFL(test_enum_t, id, color, fruit)\n\nint main() {\n  dbng\u003csqlite\u003e sqlite;\n  sqlite.connect(db);//或者开启sqcipher后sqlite.connect(db， password);\n  sqlite.execute(\"drop table if exists test_enum_t\");\n  sqlite.create_datatable\u003ctest_enum_t\u003e(ormpp_auto_key{\"id\"});\n  sqlite.insert\u003ctest_enum_t\u003e({Color::BLUE});\n  auto vec1 = sqlite.query\u003ctest_enum_t\u003e();\n  vec1.front().color = Color::RED;\n  sqlite.update(vec1.front());\n  auto vec2 = sqlite.query\u003ctest_enum_t\u003e();\n  sqlite.update\u003ctest_enum_t\u003e({Color::BLUE, BANANA, 1}, \"id=1\");\n  auto vec3 = sqlite.query\u003ctest_enum_t\u003e();\n  vec3.front().color = Color::RED;\n  sqlite.replace(vec3.front());\n  auto vec4 = sqlite.query\u003ctest_enum_t\u003e();\n  sqlite.delete_records\u003ctest_enum_t\u003e();\n  auto vec5 = sqlite.query\u003ctest_enum_t\u003e();\n  return 0;\n}\n```\n\n## 如何编译\n\n支持的选项如下:\n\t1.\tENABLE_SQLITE3\n\t2.\tENABLE_MYSQL\n\t3.\tENABLE_PG\n\ncmake -B build -DENABLE_SQLITE3=ON -DCMAKE_BUILD_TYPE=Debug\ncmake --build build --config Debug\n\n## 作为第三方库引入\n\nmysql\n```cmake\nset(ENABLE_MYSQL ON)\nadd_definitions(-DORMPP_ENABLE_MYSQL)\nadd_subdirectory(ormpp)\n```\n或者\n```cmake\nset(ENABLE_MYSQL ON)\nadd_definitions(-DORMPP_ENABLE_MYSQL)\nadd_library(ormpp INTERFACE)\ninclude(ormpp/cmake/mysql.cmake)\ntarget_link_libraries(ormpp INTERFACE ${MYSQL_LIBRARY})\ntarget_include_directories(ormpp INTERFACE ormpp ormpp/ormpp ${MYSQL_INCLUDE_DIR})\n```\n\nsqlite\n```cmake\nset(ENABLE_SQLITE3 ON)\nadd_definitions(-DORMPP_ENABLE_SQLITE3)\nadd_subdirectory(ormpp)\n```\n或者\n```cmake\nset(ENABLE_SQLITE3 ON)\nadd_definitions(-DORMPP_ENABLE_SQLITE3)\nadd_subdirectory(ormpp/thirdparty)\nadd_library(ormpp INTERFACE)\ntarget_link_libraries(ormpp INTERFACE sqlite3)\ntarget_include_directories(ormpp INTERFACE ormpp ormpp/ormpp ormpp/thirdparty/sqlite3)\n```\n\n如果需要开启sqlcipher\n\n因为sqlcipher需要链接到OpenSSL库，需要在本地先安装OpenSSL，然后添加下述cmake语句\n```cmake\nset(ENABLE_SQLITE3 ON)\nset(ENABLE_SQLITE3_CODEC)#开启sqlcipher需要同时开启ENABLE_SQLITE3和ENABLE_SQLITE3_CODEC\nadd_definitions(\n  -DORMPP_ENABLE_SQLITE3 \n  -DSQLITE_HAS_CODEC\n)\nadd_subdirectory(ormpp)\n```\n或者\n```cmake\nset(ENABLE_SQLITE3 ON)\nset(ENABLE_SQLITE3_CODEC)#开启sqlcipher需要同时开启ENABLE_SQLITE3和ENABLE_SQLITE3_CODEC\nadd_definitions(\n  -DORMPP_ENABLE_SQLITE3 \n  -DSQLITE_HAS_CODEC\n)\nadd_subdirectory(ormpp/thirdparty)\nadd_library(ormpp INTERFACE)\ntarget_link_libraries(ormpp INTERFACE sqlite3)\ntarget_include_directories(ormpp INTERFACE ormpp ormpp/ormpp ormpp/thirdparty/sqlite3)\n```\n注意：最终发布的应用程序依赖于 OpenSSL 的动态库，\n- Windows 下通常为 `libssl-3-x64.dll`和 `libcrypto-3-x64.dll`；  \n  请将这两个 `.dll` 拷贝到可执行文件所在目录。  \n- Linux下通常已安装在 `/usr/lib` 或 `/usr/local/lib`，不需要拷贝；  \n  如果你使用自编译的 OpenSSL 或者希望随同可执行文件一起分发，也可以将 `libssl.so` 与 `libcrypto.so` 放在执行目录，并通过 `LD_LIBRARY_PATH` 或者 `-Wl,-rpath` 指定查找路径。\n- macOS 下通常为 `libssl.dylib` 和 `libcrypto.dylib`；\n  请将这两个 `.dylib` 拷贝到可执行文件所在目录，或通过 `DYLD_LIBRARY_PATH`、Mach-O `@rpath` 设置查找路径。  \n\npg\n```cmake\nset(ENABLE_PG ON)\nadd_definitions(-DORMPP_ENABLE_PG)\nadd_subdirectory(ormpp)\n```\n或者\n```cmake\nset(ENABLE_PG ON)\nadd_definitions(-DORMPP_ENABLE_PG)\nadd_library(ormpp INTERFACE)\ninclude(ormpp/cmake/pgsql.cmake)\ntarget_link_libraries(ormpp INTERFACE ${PGSQL_LIBRARY})\ntarget_include_directories(ormpp INTERFACE ormpp ormpp/ormpp ${PGSQL_INCLUDE_DIR})\n```\n\n### 编译器支持\n\n需要支持C++17的编译器, 要求的编译器版本：linux gcc7.2, clang4.0; windows \u003evs2017 update5\n\n### 数据库的安装\n\n因为ormpp支持mysql和postgresql，所以需要安装mysql，postgresql，postgresql官方提供的libpq，安装之后，在CMakeLists.txt配置目录和库路径(默认安装不需要)。\n\n## 接口介绍\normpp屏蔽了不同数据库操作接口的差异，提供了统一简单的数据库操作接口，具体提供了数据库连接、断开连接、创建数据表、插入数据、更新数据、删除数据、查询数据和事务相关的接口。\n\n### 接口概览\n\n```c++\n//连接数据库\ntemplate \u003ctypename... Args\u003e\nbool connect(Args\u0026\u0026... args);\n\n//断开数据库连接\nbool disconnect();\n\n//创建数据表\ntemplate\u003ctypename T, typename... Args\u003e\nbool create_datatable(Args\u0026\u0026... args);\n\n//插入单条数据\ntemplate\u003ctypename T, typename... Args\u003e\nint insert(const T\u0026 t, Args\u0026\u0026... args);\n\n//插入多条数据\ntemplate\u003ctypename T, typename... Args\u003e\nint insert(const std::vector\u003cT\u003e\u0026 t, Args\u0026\u0026... args);\n\n//替换单条数据\ntemplate \u003ctypename T, typename... Args\u003e\nint replace(const T \u0026t, Args \u0026\u0026...args);\n\n//替换多条数据\ntemplate \u003ctypename T, typename... Args\u003e\nint replace(const std::vector\u003cT\u003e \u0026v, Args \u0026\u0026...args);\n\n//更新单条数据\ntemplate\u003ctypename T, typename... Args\u003e\nint update(const T\u0026 t, Args\u0026\u0026... args);\n\n//更新多条数据\ntemplate\u003ctypename T, typename... Args\u003e\nint update(const std::vector\u003cT\u003e\u0026 t, Args\u0026\u0026... args);\n\n//更新单条数据(指定字段)\ntemplate \u003cauto... members, typename T, typename... Args\u003e\nint update_some(const T \u0026t, Args \u0026\u0026...args);\n\n//更新多条数据(指定字段)\ntemplate \u003cauto... members, typename T, typename... Args\u003e\nint update_some(const std::vector\u003cT\u003e \u0026v, Args \u0026\u0026...args);\n\n//获取插入后的自增id\ntemplate \u003ctypename T, typename... Args\u003e\nuint64_t get_insert_id_after_insert(const T \u0026t, Args \u0026\u0026...args);\n\n//删除数据(带预处理)\ntemplate \u003ctypename T, typename... Args\u003e\nint delete_records_s(const std::string \u0026str = \"\", Args \u0026\u0026...args);\n\n//查询数据，包括单表查询和多表查询(带预处理)\ntemplate \u003ctypename T, typename... Args\u003e\nstd::vector\u003cT\u003e query_s(const std::string \u0026str = \"\", Args \u0026\u0026...args);\n\n//删除数据(不带预处理)\ntemplate \u003ctypename T, typename... Args\u003e\n[[deprecated]] bool delete_records(Args \u0026\u0026...where_condition)\n\n//查询数据，包括单表查询和多表查询(不带预处理)\ntemplate \u003ctypename T, typename... Args\u003e\n[[deprecated]] std::vector\u003cT\u003e query(Args \u0026\u0026...args);\n\n//执行原生的sql语句\nint execute(const std::string\u0026 sql);\n\n//开始事务\nbool begin();\n\n//提交事务\nbool commit();\n\n//回滚\nbool rollback();\n```\n\n### 具体的接口使用介绍\n先在entity.hpp中定义业务实体（和数据库的表对应），接着定义数据库对象：\n\n```C++\n#include \"dbng.hpp\"\n//#include \"mysql.hpp\"...等等，别忘记了\nusing namespace ormpp;\n\nstruct person {\n  int id;\n  std::string name;\n  std::optional\u003cint\u003e age; // 插入null值\n  static constexpr std::string_view get_alias_struct_name(student *) {\n    return \"CUSTOM_TABLE_NAME\";\n  }\n};\nREGISTER_AUTO_KEY(person, id)\nYLT_REFL(person, id, name, age)\n\nint main(){\n\tdbng\u003cmysql\u003e mysql;\n  dbng\u003csqlite\u003e sqlite;\n  dbng\u003cpostgresql\u003e postgres;\n\t//......\n}\n```\n\n1. 连接数据库\n```cpp\n\ttemplate \u003ctypename... Args\u003e\n\tbool connect(Args\u0026\u0026... args);\n```\n\nconnect exmple:\n\n```C++\n// mysql.connect(host, dbuser, pwd, dbname);\nmysql.connect(\"127.0.0.1\", \"root\", \"12345\", \"testdb\");\n// mysql.connect(host, dbuser, pwd, dbname, timeout, port);\nmysql.connect(\"127.0.0.1\", \"root\", \"12345\", \"testdb\", 5, 3306);\n  \npostgres.connect(\"127.0.0.1\", \"root\", \"12345\", \"testdb\");\n\nsqlite.connect(\"127.0.0.1\", \"testdb\");//或直接sqlite.connect(\"testdb\")；\n\n//开启sqlcipher后\nsqlite.connect(\"127.0.0.1\", \"root\", \"12345\", \"testdb\");//或者直接sqlite.connect(\"testdb\", \"123456\");\n```\n\n返回值：bool，成功返回true，失败返回false.\n\n2. 断开数据库连接\n```cpp\t\n\tbool disconnect();\n```\n\ndisconnect exmple:\n\n```c++\nmysql.disconnect();\n\npostgres.disconnect();\n\nsqlite.disconnect();\n```\n\n注意：用户可以不用显式调用，在数据库对象析构时会自动调用disconnect接口。\n\n返回值：bool，成功返回true，失败返回false.\n\n3. 创建数据表\n\n```C++\ntemplate\u003ctypename T, typename... Args\u003e\nbool create_datatable(Args\u0026\u0026... args);\n```\n\ncreate_datatable example:\n\n```C++\n//创建不含主键的表\nmysql.create_datatable\u003cstudent\u003e();\n\npostgres.create_datatable\u003cstudent\u003e();\n\nsqlite.create_datatable\u003cstudent\u003e();\n\n//创建含主键和not null属性的表\normpp_key key1{\"id\"};\normpp_not_null not_null{{\"id\", \"age\"}};\n\nperson p = {1, \"test1\", 2};\nperson p1 = {2, \"test2\", 3};\nperson p2 = {3, \"test3\", 4};\n\nmysql.create_datatable\u003cperson\u003e(key1, not_null);\npostgres.create_datatable\u003cperson\u003e(key1, not_null);\nsqlite.create_datatable\u003cperson\u003e(key1);\n```\n\n注意：目前只支持了key、unique和not null属性。\n```\nmysql.create_datatable\u003cperson\u003e(ormpp_unique{{\"name\"}});\n当在mysql中使用由unique声明的std::string成员创建表时，\n由于\"BLOB/TEXT column 'NAME' used in key specification without a key length\", \n故在创建表时，如果是由unique声明的std::string成员对应的数据类型则为VARCHAR(512)，否则则为TEXT\n```\n\n返回值：bool，成功返回true，失败返回false.\n\n4. 插入单条数据\n\n```C++\ntemplate\u003ctypename T, typename... Args\u003e\nint insert(const T\u0026 t, Args\u0026\u0026... args);\n```\n\ninsert example:\n\n```C++\nperson p = {1, \"test1\", 2};\nTEST_CHECK(mysql.insert(p)==1);\nTEST_CHECK(postgres.insert(p)==1);\nTEST_CHECK(sqlite.insert(p)==1);\n\n// age为null\nperson p = {1, \"test1\", {}};\nTEST_CHECK(mysql.insert(p)==1);\nTEST_CHECK(postgres.insert(p)==1);\nTEST_CHECK(sqlite.insert(p)==1);\n```\n\n返回值：int，成功返回插入数据的条数1，失败返回INT_MIN.\n\n5. 插入多条数据\n\n```C++\ntemplate\u003ctypename T, typename... Args\u003e\nint insert(const std::vector\u003cT\u003e\u0026 t, Args\u0026\u0026... args);\n```\n\nmultiple insert example:\n\n```C++\nperson p = {1, \"test1\", 2};\nperson p1 = {2, \"test2\", 3};\nperson p2 = {3, \"test3\", 4};\nstd::vector\u003cperson\u003e v1{p, p1, p2};\n\nTEST_CHECK(mysql.insert(v1)==3);\nTEST_CHECK(postgres.insert(v1)==3);\nTEST_CHECK(sqlite.insert(v1)==3);\n```\n\n返回值：int，成功返回插入数据的条数N，失败返回INT_MIN.\n\n6. 更新单条数据\n\n\n```C++\ntemplate\u003ctypename T, typename... Args\u003e\nint update(const T\u0026 t, Args\u0026\u0026... args);\n```\n\nupdate example:\n\n```C++\nperson p = {1, \"test1\", 2};\nTEST_CHECK(mysql.update(p)==1);\nTEST_CHECK(postgres.update(p)==1);\nTEST_CHECK(sqlite.update(p)==1);\n```\n\n注意：更新会根据表的key字段去更新，如果表没有key字段的时候，需要指定一个更新依据字段名，比如\n```C++\nTEST_CHECK(mysql.update(p, \"age\")==1);\nTEST_CHECK(postgres.update(p, \"age\")==1);\nTEST_CHECK(sqlite.update(p, \"age\")==1);\n```\n\n返回值：int，成功返回更新数据的条数1，失败返回INT_MIN.\n\n7. 更新多条数据\n\n```C++\ntemplate\u003ctypename T, typename... Args\u003e\nint update(const std::vector\u003cT\u003e\u0026 t, Args\u0026\u0026... args);\n```\n\nmultiple insert example:\n\n```C++\nperson p = {1, \"test1\", 2};\nperson p1 = {2, \"test2\", 3};\nperson p2 = {3, \"test3\", 4};\nstd::vector\u003cperson\u003e v1{p, p1, p2};\n\nTEST_CHECK(mysql.update(v1)==3);\nTEST_CHECK(postgres.update(v1)==3);\nTEST_CHECK(sqlite.update(v1)==3);\n```\n\n注意：更新会根据表的key字段去更新，如果表没有key字段的时候，需要指定一个更新依据字段名，用法同上。\n\n返回值：int，成功返回更新数据的条数N，失败返回INT_MIN.\n\n8. 删除数据\n```cpp\ntemplate\u003ctypename T, typename... Args\u003e\nint delete_records_s(const std::string \u0026str = \"\", Args \u0026\u0026...args);\n```\n\ndelete_records_s example:\n\n```C++\n//删除所有数据\nTEST_REQUIRE(mysql.delete_records_s\u003cperson\u003e());\nTEST_REQUIRE(postgres.delete_records_s\u003cperson\u003e());\nTEST_REQUIRE(sqlite.delete_records_s\u003cperson\u003e());\n\n//根据条件删除数据\nTEST_REQUIRE(mysql.delete_records_s\u003cperson\u003e(\"id=?\", 1));\nTEST_REQUIRE(postgres.delete_records_s\u003cperson\u003e(\"id=$1\", 1));\nTEST_REQUIRE(sqlite.delete_records_s\u003cperson\u003e(\"id=?\", 1));\n```\n\n返回值：bool，成功返回true，失败返回false.\n\n9. 查询数据\n\n```C++\ntemplate\u003ctypename T, typename... Args\u003e\nstd::vector\u003cT\u003e query_s(const std::string \u0026str = \"\", Args \u0026\u0026...args);\n```\n\nquery_s example:\n\n```C++\nauto result = mysql.query_s\u003cperson\u003e();\nTEST_CHECK(result.size()==3);\n\nauto result1 = postgres.query_s\u003cperson\u003e();\nTEST_CHECK(result1.size()==3);\n\nauto result2 = sqlite.query_s\u003cperson\u003e();\nTEST_CHECK(result2.size()==3);\n\n//可以根据条件查询\nauto result3 = mysql.query_s\u003cperson\u003e(\"id=?\", 1);\nTEST_CHECK(result3.size()==1);\n\nauto result4 = postgres.query_s\u003cperson\u003e(\"id=$1\", 2);\nTEST_CHECK(result4.size()==1);\n\nauto result5 = sqlite.query_s\u003cperson\u003e(\"id=?\", 3);\n```\n\n返回值：std::vector\u003cT\u003e，成功vector不为空，失败则为空.\n\n10. 特定列查询\n\n```C++\ntemplate\u003ctypename T, typename... Args\u003e\nstd::vector\u003cT\u003e query_s(const std::string \u0026str = \"\", Args \u0026\u0026...args);\n```\n\nsome fields query_s example:\n\n```C++\nauto result = mysql.query_s\u003cstd::tuple\u003cint, std::string, int\u003e\u003e(\"select code, name, dm from person\");\nTEST_CHECK(result.size()==3);\n\nauto result1 = postgres.query_s\u003cstd::tuple\u003cint, std::string, int\u003e\u003e(\"select code, name, dm from person\");\nTEST_CHECK(result1.size()==3);\n\nauto result2 = sqlite.query_s\u003cstd::tuple\u003cint, std::string, int\u003e\u003e(\"select code, name, dm from person\");\nTEST_CHECK(result2.size()==3);\n\nauto result3 = mysql.query_s\u003cstd::tuple\u003cint\u003e\u003e(\"select count(1) from person\");\nTEST_CHECK(result3.size()==1);\nTEST_CHECK(std::get\u003c0\u003e(result3[0])==3);\n\nauto result4 = postgres.query_s\u003cstd::tuple\u003cint\u003e\u003e(\"select count(1) from person\");\nTEST_CHECK(result4.size()==1);\nTEST_CHECK(std::get\u003c0\u003e(result4[0])==3);\n\nauto result5 = sqlite.query_s\u003cstd::tuple\u003cint\u003e\u003e(\"select count(1) from person\");\nTEST_CHECK(result5.size()==1);\nTEST_CHECK(std::get\u003c0\u003e(result5[0])==3);\n```\n\n返回值：std::vector\u003cstd::tuple\u003cT\u003e\u003e，成功vector不为空，失败则为空.\n\n11. 执行原生sql语句\n\n```C++\nint execute(const std::string\u0026 sql);\n```\n\nexecute example:\n\n```C++\nr = mysql.execute(\"drop table if exists person\");\nTEST_REQUIRE(r);\n\nr = postgres.execute(\"drop table if exists person\");\nTEST_REQUIRE(r);\n\nr = sqlite.execute(\"drop table if exists person\");\nTEST_REQUIRE(r);\n```\n\n注意：execute接口支持的原生sql语句是不带占位符的，是一条完整的sql语句。\n\n返回值：int，成功返回更新数据的条数1，失败返回INT_MIN.\n\n12. 事务接口\n\n开始事务，提交事务，回滚\n\n```C++\n//transaction\nmysql.begin();\nfor (int i = 0; i \u003c 10; ++i) {\n  person s = {i, \"tom\", 19};\n      if(!mysql.insert(s)){\n          mysql.rollback();\n          return -1;\n      }\n}\nmysql.commit();\n```\n返回值：bool，成功返回true，失败返回false.\n\n13. 面向切面编程AOP\n\n定义切面：\n\n```C++\nstruct log{\n\t//args...是业务逻辑函数的入参\n    template\u003ctypename... Args\u003e\n    bool before(Args... args){\n        std::cout\u003c\u003c\"log before\"\u003c\u003cstd::endl;\n        return true;\n    }\n\n\t//T的类型是业务逻辑返回值，后面的参数则是业务逻辑函数的入参\n    template\u003ctypename T, typename... Args\u003e\n    bool after(T t, Args... args){\n        std::cout\u003c\u003c\"log after\"\u003c\u003cstd::endl;\n        return true;\n    }\n};\n\nstruct validate{\n\t//args...是业务逻辑函数的入参\n    template\u003ctypename... Args\u003e\n    bool before(Args... args){\n        std::cout\u003c\u003c\"validate before\"\u003c\u003cstd::endl;\n        return true;\n    }\n\n\t//T的类型是业务逻辑返回值，后面的参数则是业务逻辑函数的入参\n    template\u003ctypename T, typename... Args\u003e\n    bool after(T t, Args... args){\n        std::cout\u003c\u003c\"validate after\"\u003c\u003cstd::endl;\n        return true;\n    }\n};\n```\n\n注意：切面的定义中，允许你只定义before或after，或者二者都定义。\n\n```C++\n//增加日志和校验的切面\ndbng\u003cmysql\u003e mysql;\nauto r = mysql.warper_connect\u003clog, validate\u003e(\"127.0.0.1\", \"root\", \"12345\", \"testdb\");\nTEST_REQUIRE(r);\n```\n\n## roadmap\n\n1. 支持组合键。\n1. 多表查询时增加一些诸如where, group, oder by, join, limit等常用的谓词，避免直接写sql语句。\n2. 增加日志\n3. 增加获取错误消息的接口\n4. 支持更多的数据库\n5. 增加数据库链接池\n\n\n## 联系方式\n\npurecpp@163.com\n\nqq群: 492859173\n\n[http://purecpp.cn/](http://purecpp.cn/ \"purecpp\")\n\n[https://github.com/qicosmos/ormpp](https://github.com/qicosmos/ormpp \"ormpp\")\n","funding_links":[],"categories":["C++"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fqicosmos%2Formpp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fqicosmos%2Formpp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fqicosmos%2Formpp/lists"}