【译】Simple MySQL ORM for C
一直不知道有ORM这种东西,直到和 @海坡 交流后才接触。 在项目中,需要将数据存储到数据库中,首先想到的是生成各种raw SQL的解决方法。但随着项目的进展,发现它很不灵活。譬如可能因为有新的需求,在数据库student表中添加dept_no字段,那在各种raw SQ中
一直不知道有ORM这种东西,直到和 @海坡 交流后才接触。
在项目中,需要将数据存储到数据库中,首先想到的是生成各种raw SQL的解决方法。但随着项目的进展,发现它很不灵活。譬如可能因为有新的需求,在数据库student表中添加dept_no字段,那在各种raw SQ中就需要进行修改了,工程浩大。如果操作(插入\修改\删除)数据库表中的数据,和操作数据对象一样,可以简化很多的操作,便于数据层的变更,而不必修改逻辑层代码。
//项目随手摘录的一个构造插入指定对象数据的INSERT语句的方法。 int gtd_genInsertSql(struct task_t &toinsert,char *sql, int nUserID) { int curr = 0; //task_id | user_id | strtext curr += sprintf(sql,"insert into task values(%d,%d,'%s',", toinsert.id,nUserID/*user_id*/,toinsert.strtext); //ctime char buffer[32]; ::memset(buffer,0,sizeof(buffer)); strftime(buffer,32,"'2012-%m-%d %H-%M-%S',",&(toinsert.ctime)); strncpy(sql+curr,buffer,strlen(buffer)); curr += strlen(buffer); ...... *(sql + curr) = ')'; curr++; return curr; }
ORM,即对象关系映射,ORM的设计就是数据库持久层的设计。目前流行有一些成熟的ORM框架,对应各种语言都有。
因为项目实际需要,挑选了一个轻便的框架:Simple MySQL ORM for C。google了下,只发现有Simple MySQL ORM for C作者的一篇英文博文介绍而已:http://ales.jikos.cz/smorm/。「打米量家底」,因为那篇文章不太长,所以把它翻译过来了。记得年前 @独酌逸醉 有提到过,他有翻译StackOverFlow上的精华帖。现在看来,譬如对C++熟悉,完全可以去看看外国的程序员社区。一方面你本身是程序员,专业对口,认得大多数单词;另一方面,国外高手也多,不为是提高技术的好机会;最后,它确实提高英语的好方法,赞一个。
http://ales.jikos.cz/smorm/
【译】Simple MySQL ORM for C
作者:alesak
c版本Simple MySQL ORM是用python的脚本完成的,它可以用来连接已经创建的MySQL数据库,读取数据库表所对应的数据结构,当然,也可以通过此数据结构和方法创建表。这些可以让开发者使用c语言很方便的更新/修改/删除数据库中的数据。
之前,笔者需要在强大的数据库里面存储检索结构化数据。笔者更倾向于使用MySQL和c语言。但笔者对自己写的粗糙代码和互联网上找到的巨费资源的解决方案已经很厌烦了,所以干脆自己写了一个。很简单,很天真,下笔粗糙(python不是笔者的母语,抱歉了)。但相信情人眼里出西施,笔者想象着让它更有用一点。还有,关于它的文档。。。
考虑到这只是一个技术文章,而不是一个使用手册。笔者最后取消了此文章提到的项目,所以它有待考验。不支持MySQL里头的一些数据类型。这个项目的起因之一是笔者不喜欢MySQL提供的c api,所以代之以“更时髦”的万事俱备的api~但,笔者发现它有些地方还不够好,因为笔者还没完成。
让我们开始吧。首先,你必须创建你的数据库表。笔者更喜欢一下这种方式,因为只有这样才能更充分使用数据库。
CREATE DATABASE ex1; CREATE TABLE ex_customer ( id int NOT NULL auto_increment, name char(32), PRIMARY KEY (id) ); CREATE TABLE ex_item ( customer_id int, itemname char(32) );
接下来,我们创建一个简单的python脚本db.py:
dbname = "ex1" name = "db" tables = { }
在接下来,让它执行吧 :P
python rdb.py
当然,比起真正的rock,少点听觉享受。可能你会问,笔者到底要怎么连接到数据库啊?当然,那些只是默认用户写的……但看看我们得到的结果。我们可以已经有两个文件产生了,分别是:db.h和db.c。前者包含是象征数据库表的数据结构声明和操作这些数据结构的方法;后者包含了方法的定义,接着的是数据初始化的语句。我们来看看:
typedef struct db_ex_customer { int id; char * name; } db_ex_customer; typedef struct db_ex_item { int customer_id; char * itemname; } db_ex_item;
相信没有进一步解释这些东西的必要。让我们使用它们吧!笔者新建了ex1.c文件。注意:为了更容易读懂代码,笔者没有处理错误的返回值:
#include <db.h> #include <stdio.h> #include <string.h> #include <time.h> int main (int argc, char **argv) { int ret; MYSQL global_mysql; MYSQL *m; db_ex_customer *cust1; db_ex_item *item1, *item2; mysql_init (& global_mysql); /* * connect to MySQL as usual */ m = mysql_real_connect (& global_mysql, "localhost", "root", "", "ex1", 3036, NULL, 0); /* * pass the MySQL connection to function, that initializes the "ORM" */ ret = db_init (& global_mysql); /* * the *__new method creates empty structure */ cust1 = db_ex_customer__new (); /* * setting the structure attribute with allocated string, * it will be freed during call of *__free method */ cust1->name = strdup ("alesak"); /* * this method inserts the structure into according table. * If it has serial field, its value is reflected into structure */ ret = db_ex_customer__insert (cust1); item1 = db_ex_item__new (); /* * let's use the serial value from newly inserted customer */ item1->customer_id = cust1->id; item1->itemname = strdup ("simple orm"); ret = db_ex_item__insert (item1); item2 = db_ex_item__new (); item2->customer_id = cust1->id; item2->itemname = strdup ("advanced orm"); ret = db_ex_item__insert (item2); db_ex_customer__free (cust1); db_ex_item__free (item1); db_ex_item__free (item2); return (0); }</time.h></string.h></stdio.h></db.h>
编译下:
cc -I `mysql_config --cflags` ex1.c db.c `mysql_config --libs` -o ex1
运行可执行文件,发现它没错。这意味着,它已经一些数据已被存储。至少如果你让评价它,笔者会说很优雅。接下来,怎么去检索这些数据?假设,我们已经知道数据库表中记录的键值,笔者又新建了ex2.c文件。
#define _XOPEN_SOURCE 500 #include <db.h> #include <stdio.h> #include <string.h> #include <time.h> int main (int argc, char **argv) { int ret; MYSQL global_mysql; MYSQL *m; db_ex_customer *cust1; db_ex_item *item1, *item2; mysql_init (& global_mysql); m = mysql_real_connect (& global_mysql, "localhost", "root", "", "ex1", 3036, NULL, 0); ret = db_init (& global_mysql); cust1 = db_ex_customer__get_by_id (3); if (cust1) { fprintf (stdout, "I have customer named \'%s\'\n", cust1->name); db_ex_customer__free (cust1); } return (0); }</time.h></string.h></stdio.h></db.h>
跟前边一样,编译,然后执行:
cc -I. `mysql_config --cflags` ex2.c db.c `mysql_config --libs` -o ex2 ./ex2
最后,笔者不想让ORM自动创建相关数据的查询,因为笔者相信它能做的好。(老实说,如果使用默认的MyISAM,它不可能判断相关数据)。当然,接下来笔者想要新建笔者自己的、超复杂的ex_items表与ex_customer标连接后的SELECT检索。编辑一下db.py:
dbname = "ex1" name = "db" tables = { "ex_item" :[("get", "get_customer_items", [("INTEGER", "customer_id")], "SELECT ex_item.* FROM ex_item WHERE customer_id = ?")] }
重新执行db.puy脚本会添加新的db_ex_item__get_customer_items_*方法集。这些方法灵活之处在于,可以增加INTEGER类型的参数,在特定的SQL上打开游标:从游标读取一行记录,关闭游标。我们扩展ex2.c:
#define _XOPEN_SOURCE 500 #include <db.h> #include <stdio.h> #include <string.h> #include <time.h> int main (int argc, char **argv) { int ret; MYSQL global_mysql; MYSQL *m; db_ex_customer *cust1; db_ex_item *item1, *item2; mysql_init (& global_mysql); m = mysql_real_connect (& global_mysql, "localhost", "root", "", "ex1", 3036, NULL, 0); ret = db_init (& global_mysql); cust1 = db_ex_customer__get_by_id (3); if (cust1) { fprintf (stdout, "I have customer named \'%s\'..\n", cust1->name); db_ex_item__get_customer_items_open (cust1->id); while ((item1 = db_ex_item__get_customer_items_fetch ()) != NULL) { fprintf (stdout, ".. and found his item named \'%s\'\n", item1->itemname); db_ex_item__free (item1); } db_ex_item__get_customer_items_close (); db_ex_customer__free (cust1); } return (0); }</time.h></string.h></stdio.h></db.h>
得偿所愿,它打印的结果:
I have customer named 'alesak'.. .. and found his item named 'simple orm' .. and found his item named 'advanced orm'
以上,朋友们!这里是http://ales.jikos.cz/smorm/rdb.py 脚本。更确切的说,别下载这个破烂东西。但如果你喜欢这个点子,请告诉笔者:alesak#gmail.com。全文完。
感谢作者 @alesak。Simple MySQL ORM for C我没有亲手测试,找时间补上测试篇。另,笔者水平有限,欢迎扶正拍砖。以上。
捣乱 2013-3-22
http://daoluan.net

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

利用地理空间技术高效处理700万条记录并创建交互式地图本文探讨如何使用Laravel和MySQL高效处理超过700万条记录,并将其转换为可交互的地图可视化。初始挑战项目需求:利用MySQL数据库中700万条记录,提取有价值的见解。许多人首先考虑编程语言,却忽略了数据库本身:它能否满足需求?是否需要数据迁移或结构调整?MySQL能否承受如此大的数据负载?初步分析:需要确定关键过滤器和属性。经过分析,发现仅少数属性与解决方案相关。我们验证了过滤器的可行性,并设置了一些限制来优化搜索。地图搜索基于城

DevOps工程师常面临RDS数据库优化与更新的挑战,尤其在高负载情况下,传统方法易导致停机风险。本文介绍AWS蓝/绿部署策略,实现RDS数据库零停机时间更新。告别数据库更新停机噩梦!本文将详细讲解蓝/绿部署策略,并提供AWS环境下的操作步骤,助您在不影响服务可用性的前提下,更新RDS数据库实例。准备工作首先,协调开发团队,选择工作负载流量最低的时段进行更新。良好的DevOps实践建议提前通知团队。本例演示如何利用蓝/绿部署,在零停机时间内缩减数据库实例存储空间。您可以通过AWSRDS控制台

MySQL 可在无需网络连接的情况下运行,进行基本的数据存储和管理。但是,对于与其他系统交互、远程访问或使用高级功能(如复制和集群)的情况,则需要网络连接。此外,安全措施(如防火墙)、性能优化(选择合适的网络连接)和数据备份对于连接到互联网的 MySQL 数据库至关重要。

MySQL启动失败的原因有多种,可以通过检查错误日志进行诊断。常见原因包括端口冲突(检查端口占用情况并修改配置)、权限问题(检查服务运行用户权限)、配置文件错误(检查参数设置)、数据目录损坏(恢复数据或重建表空间)、InnoDB表空间问题(检查ibdata1文件)、插件加载失败(检查错误日志)。解决问题时应根据错误日志进行分析,找到问题的根源,并养成定期备份数据的习惯,以预防和解决问题。

MySQL使用共享锁和排他锁管理并发,提供表锁、行锁和页锁三种锁类型。行锁可提高并发性,使用FOR UPDATE语句可给行加排他锁。悲观锁假设冲突,乐观锁通过版本号判断数据修改。常见锁表问题表现为查询缓慢,使用SHOW PROCESSLIST命令查看锁持有的查询。优化措施包括选择合适索引、减少事务范围、批量操作和优化SQL语句。

MySQL数据库操作中,字符串处理是不可避免的环节。SUBSTRING_INDEX函数正是为此而设计的,它能高效地根据分隔符提取子字符串。SUBSTRING_INDEX函数应用示例以下示例展示了SUBSTRING_INDEX函数的灵活性和实用性:从URL中提取特定部分例如,提取域名:SELECTSUBSTRING_INDEX('www.mysql.com','.',2);提取文件扩展名轻松获取文件扩展名:SELECTSUBSTRING_INDEX('file.pdf','.',-1);处理不存在

对于生产环境,通常需要一台服务器来运行 MySQL,原因包括性能、可靠性、安全性和可扩展性。服务器通常拥有更强大的硬件、冗余配置和更严格的安全措施。对于小型、低负载应用,可在本地机器运行 MySQL,但需谨慎考虑资源消耗、安全风险和维护成本。如需更高的可靠性和安全性,应将 MySQL 部署到云服务器或其他服务器上。选择合适的服务器配置需要根据应用负载和数据量进行评估。

MySQL 和 MariaDB 可以共存,但需要谨慎配置。关键在于为每个数据库分配不同的端口号和数据目录,并调整内存分配和缓存大小等参数。连接池、应用程序配置和版本差异也需要考虑,需要仔细测试和规划以避免陷阱。在资源有限的情况下,同时运行两个数据库可能会导致性能问题。
