在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_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;iid=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
這只是針對單一表的查詢操作,可以加入count(*)功能。int count;
select_table((void**)&count,SELECT_("count(*)",User,"1=1"));
對於其它的表,你只要創建一個相當於User的結構體就可以了,再添加一個 select_value_item_user 功能數據庫值與此綁定功能的函數,再在select中選擇這個函數就可,
當然,可以采用C 下的 HashMap 來把 表名(結構體名)與 綁定函數 做一個映像,這樣方便一點,但我的表只有幾個所以就不用做了。