標籤:
在java/C#中都有類的反射,而C下是不存在的。
java/C#中能夠把表設計成類。而C下僅僅能設計成結構體形式。
在java中有hibernate來操作資料庫,可是在C以下怎麼設計好呢?
如今,我想出了一個點子,下面使用sqlite
先建立一個結構體。表示一張資料庫表的結構。
typedef struct User {
int id;
char *name;
char *password;
} User;
建立表的語句:
CREATE TABLE ‘User‘ (‘id‘ INTEGER PRIMARY KEY AUTOINCREMENT,‘name‘ varchar(100),‘password‘ varchar(100),‘workNumber‘ varchar(100))
資料庫的操作有select ,insert ,delete ,update,而insert,delete,update都是讓資料庫去操作,但select是有返回資料的。
所以。對於insert,delete,update我採用
int sql_exec(char *format,...) {char sql[1024];va_list args;char *errmsg=NULL;int rc;va_start(args, format); vsprintf(sql,format,args);va_end(args);rc=sqlite3_exec(g_mdb,sql,NULL,NULL,&errmsg);if(rc!=SQLITE_OK){printf("%s,%s,%s\n",__FUNCTION__,errmsg,sql);sqlite3_free(errmsg);return SQLITE_ERROR;}return SQLITE_OK;}
對資料庫的操作我定義成
#define SELECT_(_columns,_table,_where) "select "_columns" from "#_table" WHERE "##_where#define INSERT_INTO_(_table,_columns,_values) "insert into "#_table" ("_columns") values ("_values")"#define UPDATE_(_table,_set,_where) "UPDATE "#_table" SET "_set" WHERE "##_where#define DELETE_FROM(_table,_where) "DELETE FROM "#_table" WHERE "##_where
#define insert_table(format,...) sql_exec(format,__VA_ARGS__)
#define update_table(format,...) sql_exec(format,__VA_ARGS__)
#define delete_table(format,...) sql_exec(format,__VA_ARGS__)
終於調用(insert):
insert_table(INSERT_INTO_(User,"id,name,password","%d,‘%s‘,‘%s‘"),us.id,us.name,us.password);
而對於select ,返回的是一個列表資料:
struct select_list {void *value;struct select_list *next;};typedef void select_value_free(void *value);struct select_list *select_list_new(){struct select_list *h=(struct select_list*)malloc(sizeof(struct select_list));memset(h,0,sizeof(struct select_list));return h;}void select_list_free(struct select_list *list,select_value_free value_free){struct select_list *next;if(list==NULL){return ;}if(list->value){value_free(list->value);}if(list) {next=list->next;free(list);}select_list_free(next,value_free);}
select_list *home;
select_table((void**)&home,SELECT_("id",User,"name=‘%s‘ and password=‘%s‘"),us.name,us.password);
if(home!=NULL){
for(next=home;next;next=next->next){
User *item=((User*)next->value);
printf("%d,%s,%s\n",item->id,item->name,item->password);
}
select_list_free(home,user_free);
}
//關鍵是在select_table
通過sqlite3_prepare尋找出sqlite3_stmt,遍曆stmt,取出當前操作的表名。與定義的結構體user比較,假設等於。則建立User,把查詢的資料給User,再把這個User增加鏈表value就能夠了。
void *select_value_item_user(sqlite3_stmt *stmt){int i;int count;User *item=(User*)malloc(sizeof(User));memset(item,0,sizeof(User));count=sqlite3_column_count(stmt);for(i=0;i<count;i++){if(0==strcmp(sqlite3_column_name(stmt,i),"id")){item->id=sqlite3_column_int(stmt,i);}if(0==strcmp(sqlite3_column_name(stmt,i),"name")){char_cpy(&item->name,(const char *)sqlite3_column_text(stmt,i));}}return item;}
int select_table(void **result,char *pszFormat,...) {sqlite3_stmt * stmt=NULL; const char *table_name=NULL;int count=0;char sql[1024];va_list args; struct select_list *next=NULL;struct select_list *home=NULL;va_start(args, pszFormat); vsprintf(sql,pszFormat,args);va_end(args);printf("%s\n",sql);*result=NULL;if(sqlite3_prepare(g_mdb,sql,-1,&stmt,NULL)==SQLITE_OK){while( sqlite3_step(stmt)==SQLITE_ROW){/************************************************************************//* *//************************************************************************/table_name=sqlite3_column_table_name(stmt,0);if(table_name) {if(strcmp(table_name,STR(User))==0){//加入到list就能夠了next=select_list_new();next->value=select_value_item_user(stmt);next->next=NULL;if(*result==NULL){*result=next;} else {home->next=next;}home=next;}} else {{int column_count=sqlite3_column_count(stmt);int i=0;for(i=0;i<column_count;i++){if(sqlite3_column_type(stmt,i)==SQLITE_INTEGER) {//printf("%s,%d\n",sqlite3_column_name(stmt,i),sqlite3_column_int(stmt,i));*result=(void*)sqlite3_column_int(stmt,i);}}}}count++;}} else {count=-1;//save errmsg...}sqlite3_finalize(stmt);return count;}
這僅僅是針對單一表的查詢操作,能夠增加count(*)功能。
int count;
select_table((void**)&count,SELECT_("count(*)",User,"1=1"));
對於其他的表,你僅僅要建立一個相當於User的結構體就能夠了。再加入一個 select_value_item_user 功能資料庫值與此綁定功能的函數。再在select中選擇這個函數就可。
當然,能夠採用C 下的 HashMap 來把 表名(結構體名)與 綁定函數 做一個映像,這樣方便一點,但我的表僅僅有幾個所以就不用做了。
c語言下的通用資料庫介面(之sqlite消化,類比c#,java的反射)