NexusForce 1.0.0
A rigorously engineered full-stack C++ backend library.
载入中...
搜索中...
未找到
repository.hpp
浏览该文件的文档.
1#ifndef NEFORCE_DATABASE_REPOSITORY_HPP__
2#define NEFORCE_DATABASE_REPOSITORY_HPP__
3
23
30NEFORCE_BEGIN_NAMESPACE__
31
37
46template <typename T, typename Connect = idb_tb_connect>
48 static_assert(is_base_of_v<idb_connect, Connect>, "Connect must be derived from idb_connect");
49
50 Connect& conn_;
51
55 static string build_insert_with_values(const T& entity) {
57 const string tbl = sql_mapper<T>::table_name();
58
60 vector<string> columns;
61 vector<string> vals;
62
63 for (const auto& entry: meta->all_properties()) {
64 const auto* prop = entry.second;
65 if (prop->is_transient() || prop->is_auto_increment()) {
66 continue;
67 }
68 columns.push_back(prop->name());
69 const reflect::meta_any val = prop->get(&entity);
71 }
72
73 b.insert_into(tbl, columns);
74 b.values(vals);
75 return b.build();
76 }
77
81 static string build_update_with_values(const T& entity) {
83 const string tbl = sql_mapper<T>::table_name();
84
85 const reflect::meta_property* pk = nullptr;
86 for (const auto& entry: meta->all_properties()) {
87 if (entry.second->is_primary_key()) {
88 pk = entry.second;
89 break;
90 }
91 }
92 if (pk == nullptr) {
93 NEFORCE_THROW_EXCEPTION(value_exception("repository::update: no primary key defined"));
94 }
95
97 b.update(tbl);
98
99 for (const auto& entry: meta->all_properties()) {
100 const auto* prop = entry.second;
101 if (prop->is_transient() || prop->is_primary_key() || prop->is_auto_increment()) {
102 continue;
103 }
104 const reflect::meta_any val = prop->get(&entity);
105 b.set(prop->name(), meta_any_to_sql_literal(val));
106 }
107
108 const reflect::meta_any pk_val = pk->get(&entity);
109 b.where_eq(pk->name(), meta_any_to_sql_literal(pk_val));
110 return b.build();
111 }
112
116 static string build_delete_with_pk(const T& entity) {
117 const auto pkv = sql_mapper<T>::get_pk_value(entity);
118 const string tbl = sql_mapper<T>::table_name();
119
121 const reflect::meta_property* pk = nullptr;
122 for (const auto& entry: meta->all_properties()) {
123 if (entry.second->is_primary_key()) {
124 pk = entry.second;
125 break;
126 }
127 }
128 if (pk == nullptr) {
129 NEFORCE_THROW_EXCEPTION(value_exception("repository::remove: no primary key defined"));
130 }
131
132 sql_builder b;
133 b.delete_from(tbl);
135 return b.build();
136 }
137
138public:
143 explicit repository(Connect& conn) noexcept :
144 conn_(conn) {}
145
150 NEFORCE_NODISCARD Connect& connection() noexcept { return conn_; }
151
157 bool create_table(string_view table_override = "") {
158 const string sql = sql_mapper<T>::create_table_sql(table_override);
159 return conn_.update(sql);
160 }
161
167 bool drop_table(string_view table_override = "") {
168 const string sql = sql_mapper<T>::drop_table_sql(table_override);
169 return conn_.update(sql);
170 }
171
178 const string tbl = sql_mapper<T>::table_name();
180
181 const reflect::meta_property* pk = nullptr;
182 for (const auto& entry: meta->all_properties()) {
183 if (entry.second->is_primary_key()) {
184 pk = entry.second;
185 break;
186 }
187 }
188 if (pk == nullptr) {
189 return nullptr;
190 }
191
192 sql_builder b;
193 for (const auto& entry: meta->all_properties()) {
194 if (entry.second->is_transient()) {
195 continue;
196 }
197 b.select(entry.second->name());
198 }
199 b.from(tbl);
201
202 auto result = conn_.query(b.build());
203 if (result == nullptr || result->empty()) {
204 return nullptr;
205 }
206
207 if (!result->next()) {
208 return nullptr;
209 }
210
212 }
213
219 const string tbl = sql_mapper<T>::table_name();
221
222 sql_builder b;
223 for (const auto& entry: meta->all_properties()) {
224 if (entry.second->is_transient()) {
225 continue;
226 }
227 b.select(entry.second->name());
228 }
229 b.from(tbl);
230
231 auto result = conn_.query(b.build());
232 return sql_mapper<T>::from_result(move(result));
233 }
234
240 vector<T> find_where(const string& where_clause) {
241 const string tbl = sql_mapper<T>::table_name();
243
244 sql_builder b;
245 for (const auto& entry: meta->all_properties()) {
246 if (entry.second->is_transient()) {
247 continue;
248 }
249 b.select(entry.second->name());
250 }
251 b.from(tbl);
252 b.where(where_clause);
253
254 auto result = conn_.query(b.build());
255 return sql_mapper<T>::from_result(move(result));
256 }
257
265 vector<T> find_page(const size_t page_num, const size_t page_size, string_view order_by = "") {
266 const string tbl = sql_mapper<T>::table_name();
268
269 sql_builder b;
270 for (const auto& entry: meta->all_properties()) {
271 if (entry.second->is_transient()) {
272 continue;
273 }
274 b.select(entry.second->name());
275 }
276 b.from(tbl);
277
278 if (!order_by.empty()) {
279 b.order_by_asc(order_by);
280 }
281
282 b.page(static_cast<int>(page_num), static_cast<int>(page_size));
283
284 auto result = conn_.query(b.build());
285 return sql_mapper<T>::from_result(move(result));
286 }
287
296 bool insert(T& entity) {
297 const string sql = build_insert_with_values(entity);
298 return conn_.update(sql);
299 }
300
306 bool update(const T& entity) {
307 const string sql = build_update_with_values(entity);
308 return conn_.update(sql);
309 }
310
316 bool remove(const T& entity) {
317 const string sql = build_delete_with_pk(entity);
318 return conn_.update(sql);
319 }
320
325 size_t count() {
326 const string tbl = sql_mapper<T>::table_name();
327 sql_builder b;
328 b.select_count();
329 b.from(tbl);
330
331 auto result = conn_.query(b.build());
332 if (result == nullptr || result->empty()) {
333 return 0;
334 }
335 if (!result->next()) {
336 return 0;
337 }
338 return static_cast<size_t>(result->get_int64(0));
339 }
340
345 bool table_exists() { return conn_.table_exists(sql_mapper<T>::table_name()); }
346};
347 // Repository
349
350NEFORCE_END_NAMESPACE__
351#endif // NEFORCE_DATABASE_REPOSITORY_HPP__
属性反射元数据类
string_view name() const noexcept
获取属性名称
meta_any get(const void *obj) const
获取属性值
static registry & instance()
获取单例实例
unique_ptr< T > find_by_id(const reflect::meta_any &id)
按主键查找实体
bool table_exists()
检查表是否存在
bool insert(T &entity)
插入实体
vector< T > find_where(const string &where_clause)
按 WHERE 条件查询实体
vector< T > find_page(const size_t page_num, const size_t page_size, string_view order_by="")
分页查询实体
bool remove(const T &entity)
删除实体(按主键)
repository(Connect &conn) noexcept
构造函数
size_t count()
获取实体总数
bool create_table(string_view table_override="")
创建数据库表
vector< T > find_all()
查询全部实体
bool drop_table(string_view table_override="")
删除数据库表
bool update(const T &entity)
更新实体(按主键)
Connect & connection() noexcept
获取内部连接引用
sql_builder & where_eq(string field, string value)
添加相等条件
sql_builder & from(string table) noexcept
设置主表
sql_builder & order_by_asc(string field)
添加升序排序
sql_builder & select_count(string field, string alias)
添加COUNT聚合函数(带别名)
sql_builder & page(int page_num, int page_size)
添加分页
sql_builder & values(vector< string > values)
设置VALUES占位符
sql_builder & where(string condition)
添加WHERE条件
string build() const
构建最终的SQL语句
sql_builder & select(vector< string > fields)
列表设置SELECT字段
sql_builder & update(string table)
设置UPDATE表名
sql_builder & delete_from(string table)
设置DELETE FROM表名
sql_builder & insert_into(string table, vector< string > fields)
设置INSERT INTO表名和字段
sql_builder & set(string assignment)
添加SET赋值
static string create_table_sql(string_view table_override="")
生成 CREATE TABLE SQL
static T from_row(const idb_tb_result &row, const unordered_map< string, size_t > &col_map={})
从结果行构建实体对象
static reflect::meta_any get_pk_value(const T &entity)
获取主键值
static vector< T > from_result(unique_ptr< idb_tb_result > result)
从查询结果集构建实体对象列表
static string drop_table_sql(string_view table_override="")
生成 DROP TABLE SQL
static string table_name()
获取映射的表名
独占智能指针
动态大小数组容器
constexpr void push_back(const T &value)
在末尾拷贝插入元素
数据库抽象接口层
constexpr bool is_base_of_v
is_base_of的便捷变量模板
constexpr type_id type_id_for() noexcept
计算类型 T 的运行时期类型标识
string meta_any_to_sql_literal(const reflect::meta_any &val)
将 meta_any 值转换为 SQL 字面量字符串
constexpr Iterator2 move(Iterator1 first, Iterator1 last, Iterator2 result) noexcept(noexcept(inner::__move_aux(first, last, result)))
移动范围元素
basic_string_view< char > string_view
字符字符串视图
constexpr unique_ptr< T > make_unique(Args &&... args)
创建unique_ptr
反射系统主入口
SQL语句构建器
ORM 对象-关系映射器
独占智能指针
动态大小数组容器