mysql orm c语言_【译】Simple MySQL ORM for C
一直不知道有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++熟悉,完全可以去看看外國的程序員社區。一方面你本身是程序員,專業對口,認得大多數單詞;另一方面,國外高手也多,不為是提高技術的好機會;最后,它確實提高英語的好方法,贊一個。
下面是《Simple MySQL ORM for 》的譯文,原文鏈接: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
#include
#include
#include
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);
}
編譯下:
cc -I `mysql_config --cflags` ex1.c db.c `mysql_config --libs` -o ex1
運行可執行文件,發現它沒錯。這意味著,它已經一些數據已被存儲。至少如果你讓評價它,筆者會說很優雅。接下來,怎么去檢索這些數據?假設,我們已經知道數據庫表中記錄的鍵值,筆者又新建了ex2.c文件。
#define _XOPEN_SOURCE 500
#include
#include
#include
#include
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);
}
跟前邊一樣,編譯,然后執行:
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
#include
#include
#include
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);
}
得償所愿,它打印的結果:
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
總結
以上是生活随笔為你收集整理的mysql orm c语言_【译】Simple MySQL ORM for C的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql 消息队列_MYSQL模拟消息
- 下一篇: Python实现简单的学生管理系统