查看: 159994|回复: 656

[PRO*C] 看我做的数据库包装器

[复制链接]
论坛徽章:
14
2009新春纪念徽章
日期:2009-01-04 14:52:28沸羊羊
日期:2015-03-04 14:51:52优秀写手
日期:2014-03-14 06:00:13马上有房
日期:2014-02-18 16:42:022014年新春福章
日期:2014-02-18 16:42:022013年新春福章
日期:2013-02-25 14:51:24ITPUB 11周年纪念徽章
日期:2012-10-09 18:08:15蜘蛛蛋
日期:2012-06-27 21:08:142012新春纪念徽章
日期:2012-01-04 11:53:29ITPUB十周年纪念徽章
日期:2011-11-01 16:23:26
跳转到指定楼层
1#
发表于 2008-11-18 15:40 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
用C语言在LINUX下写的,OCI环境。:
/* DTO 测试程序,DTO=Data Transfer Object */
#include <DTO_utility.h>
//SQL_Connect是数据库句柄,前边程序打开的。
int getxw(T_SQL_Connect *SQL_Connect,char *Train_no,INT4 today,char *carno)
{
DTO seat_DTO;
int ret;
char stmt[4096],buf[100],*p;
JSON_OBJECT *json;

/* 没有模板,自动生成 */
        ret=DTO_init(&seat_DTO,SQL_Connect,"SEAT",0,0);
        if(ret) {
                printf("DTO_init fail %d!\n",ret);
                return -1;
        }

        p=stmt;
        p+=sprintf(p,"where start_date=to_date('%s','YYYY-MM-DD') ",
                rjultostrfmt(buf,today,"YYYY-MM-DD")); //日期转字符串
        if(Train_no && *Train_no) //组装车次
                p+=sprintf(p,"and train_no='%s' ",Train_no);
        if(carno && *carno) //组装车厢号
                p+=sprintf(p,"and carno='%s' ",carno);
//执行select语句
        ret=DTO_get1(&seat_DTO,stmt,10);
/* 生成并执行了如下语句:
   DTO_get1:SELECT  to_char(START_DATE,'YYYY-MM-DD') START_DATE,BEG_STATION,TRAIN_NO,RUN_TRAIN,
to_char(ON_DATE,'YYYY-MM-DD HH24:MI') ON_DATE,CARNO,SEAT_TYPE,SEAT_NO,END_STATION,
SHORTEST_STATION,PURPOSE,GRIDE,PRO,FLAG,USED_DEV,USED_UID,
to_char(USED_TIME,'YYYY-MM-DD HH24:MI:SS') USED_TIME,ROWID
FROM TICKET.SEAT
where start_date=to_date('2008-11-18','YYYY-MM-DD') and train_no='H4' ,
ret=10
*/
        if(ret <= 0) {
                printf("err:%s\n",stmt);
                return -1;
        }
        while(!DTO_next(&seat_DTO)) { //从结果集取下一条记录
                json=json_object_new_object();
                if(!json) {
                        printf("new json fail!\n");
                        continue;
                }
                DTO_toJSON(&seat_DTO,json,0);
                printf("seat:%s\n",json_object_get_string(json));
                json_object_put(json);
        }

        DTO_free(&seat_DTO); //释放结果集,关闭游标
        return 0;
}

这个题目就是为此类目的而生:
http://www.itpub.net/thread-1110578-1-4.html
不仅是不知道表名,简直什么都不知道。
如果写程序?就需要高度抽象的编程框架。只有高度抽象,才能高度通用(这个框架的抽象程度并不算高,在此基础上能够写出更抽象的框架)。程序抽象,一直是高级编程的追求目标。既要抽象,又要高效,是我写C环境框架的初衷。

[ 本帖最后由 yulihua49 于 2009-6-26 10:03 编辑 ]
论坛徽章:
14
2009新春纪念徽章
日期:2009-01-04 14:52:28沸羊羊
日期:2015-03-04 14:51:52优秀写手
日期:2014-03-14 06:00:13马上有房
日期:2014-02-18 16:42:022014年新春福章
日期:2014-02-18 16:42:022013年新春福章
日期:2013-02-25 14:51:24ITPUB 11周年纪念徽章
日期:2012-10-09 18:08:15蜘蛛蛋
日期:2012-06-27 21:08:142012新春纪念徽章
日期:2012-01-04 11:53:29ITPUB十周年纪念徽章
日期:2011-11-01 16:23:26
2#
 楼主| 发表于 2008-11-18 15:43 | 只看该作者

执行结果:得到10个rows,用JSON格式打印

tuxticket@jgbticket:~/src> ./tDTO.sh -cH4
seat:{ "START_DATE": "2008-11-18", "BEG_STATION": "BDHP", "TRAIN_NO": "H4", "RUN_TRAIN": "H4",
"ON_DATE": "2008-11-18 13:32", "CARNO": "4", "SEAT_TYPE": "12", "SEAT_NO": "1", "END_STATION": "6",
"SHORTEST_STATION": "0", "PURPOSE": "0", "GRIDE": "G04", "PRO": "", "FLAG": "0", "USED_DEV": "xwfb",
"USED_UID": "xwfb", "USED_TIME": "2008-10-19 02:00:03", "ROWID": "AAAM3iAAFAAAEKmABN" }

seat:{ "START_DATE": "2008-11-18", "BEG_STATION": "BDHP", "TRAIN_NO": "H4", "RUN_TRAIN": "H4",
"ON_DATE": "2008-11-18 13:32", "CARNO": "4", "SEAT_TYPE": "12", "SEAT_NO": "2", "END_STATION": "6",
"SHORTEST_STATION": "0", "PURPOSE": "0", "GRIDE": "G04", "PRO": "", "FLAG": "0", "USED_DEV": "xwfb",
"USED_UID": "xwfb", "USED_TIME": "2008-10-19 02:00:03", "ROWID": "AAAM3iAAFAAAEKmABO" }

seat:{ "START_DATE": "2008-11-18", "BEG_STATION": "BDHP", "TRAIN_NO": "H4", "RUN_TRAIN": "H4",
"ON_DATE": "2008-11-18 13:32", "CARNO": "4", "SEAT_TYPE": "12", "SEAT_NO": "3", "END_STATION": "6",
"SHORTEST_STATION": "0", "PURPOSE": "0", "GRIDE": "G04", "PRO": "", "FLAG": "0", "USED_DEV": "xwfb",
"USED_UID": "xwfb", "USED_TIME": "2008-10-19 02:00:03", "ROWID": "AAAM3iAAFAAAEKmABP" }

seat:{ "START_DATE": "2008-11-18", "BEG_STATION": "BDHP", "TRAIN_NO": "H4", "RUN_TRAIN": "H4",
"ON_DATE": "2008-11-18 13:32", "CARNO": "4", "SEAT_TYPE": "12", "SEAT_NO": "4", "END_STATION": "6",
"SHORTEST_STATION": "0", "PURPOSE": "0", "GRIDE": "G04", "PRO": "", "FLAG": "0", "USED_DEV": "xwfb",
"USED_UID": "xwfb", "USED_TIME": "2008-10-19 02:00:03", "ROWID": "AAAM3iAAFAAAEKmABQ" }

seat:{ "START_DATE": "2008-11-18", "BEG_STATION": "BDHP", "TRAIN_NO": "H4", "RUN_TRAIN": "H4",
"ON_DATE": "2008-11-18 13:32", "CARNO": "4", "SEAT_TYPE": "12", "SEAT_NO": "5", "END_STATION": "6",
"SHORTEST_STATION": "0", "PURPOSE": "0", "GRIDE": "G04", "PRO": "", "FLAG": "0", "USED_DEV": "xwfb",
"USED_UID": "xwfb", "USED_TIME": "2008-10-19 02:00:03", "ROWID": "AAAM3iAAFAAAEKmABR" }

seat:{ "START_DATE": "2008-11-18", "BEG_STATION": "BDHP", "TRAIN_NO": "H4", "RUN_TRAIN": "H4",
"ON_DATE": "2008-11-18 13:32", "CARNO": "4", "SEAT_TYPE": "12", "SEAT_NO": "6", "END_STATION": "6",
"SHORTEST_STATION": "0", "PURPOSE": "0", "GRIDE": "G04", "PRO": "", "FLAG": "0", "USED_DEV": "xwfb",
"USED_UID": "xwfb", "USED_TIME": "2008-10-19 02:00:03", "ROWID": "AAAM3iAAFAAAEKmABS" }
seat:{ "START_DATE": "2008-11-18", "BEG_STATION": "BDHP", "TRAIN_NO": "H4", "RUN_TRAIN": "H4",
"ON_DATE": "2008-11-18 13:32", "CARNO": "4", "SEAT_TYPE": "12", "SEAT_NO": "7", "END_STATION": "6",
"SHORTEST_STATION": "0", "PURPOSE": "0", "GRIDE": "G04", "PRO": "", "FLAG": "0", "USED_DEV": "xwfb",
"USED_UID": "xwfb", "USED_TIME": "2008-10-19 02:00:03", "ROWID": "AAAM3iAAFAAAEKmABT" }

seat:{ "START_DATE": "2008-11-18", "BEG_STATION": "BDHP", "TRAIN_NO": "H4", "RUN_TRAIN": "H4",
"ON_DATE": "2008-11-18 13:32", "CARNO": "4", "SEAT_TYPE": "12", "SEAT_NO": "8", "END_STATION": "6",
"SHORTEST_STATION": "0", "PURPOSE": "0", "GRIDE": "G04", "PRO": "", "FLAG": "0", "USED_DEV": "xwfb",
"USED_UID": "xwfb", "USED_TIME": "2008-10-19 02:00:03", "ROWID": "AAAM3iAAFAAAEKmABU" }

seat:{ "START_DATE": "2008-11-18", "BEG_STATION": "BDHP", "TRAIN_NO": "H4", "RUN_TRAIN": "H4",
"ON_DATE": "2008-11-18 13:32", "CARNO": "4", "SEAT_TYPE": "12", "SEAT_NO": "9", "END_STATION": "6",
"SHORTEST_STATION": "0", "PURPOSE": "0", "GRIDE": "G04", "PRO": "", "FLAG": "0", "USED_DEV": "xwfb",
"USED_UID": "xwfb", "USED_TIME": "2008-10-19 02:00:03", "ROWID": "AAAM3iAAFAAAEKmABV" }

seat:{ "START_DATE": "2008-11-18", "BEG_STATION": "BDHP", "TRAIN_NO": "H4", "RUN_TRAIN": "H4",
"ON_DATE": "2008-11-18 13:32", "CARNO": "4", "SEAT_TYPE": "12", "SEAT_NO": "10", "END_STATION": "6",
"SHORTEST_STATION": "0", "PURPOSE": "0", "GRIDE": "G04", "PRO": "", "FLAG": "0", "USED_DEV": "xwfb",
"USED_UID": "xwfb", "USED_TIME": "2008-10-19 02:00:03", "ROWID": "AAAM3iAAFAAAEKmABW" }
tuxticket@jgbticket:~/src>

[ 本帖最后由 yulihua49 于 2008-11-18 16:10 编辑 ]

使用道具 举报

回复
论坛徽章:
14
2009新春纪念徽章
日期:2009-01-04 14:52:28沸羊羊
日期:2015-03-04 14:51:52优秀写手
日期:2014-03-14 06:00:13马上有房
日期:2014-02-18 16:42:022014年新春福章
日期:2014-02-18 16:42:022013年新春福章
日期:2013-02-25 14:51:24ITPUB 11周年纪念徽章
日期:2012-10-09 18:08:15蜘蛛蛋
日期:2012-06-27 21:08:142012新春纪念徽章
日期:2012-01-04 11:53:29ITPUB十周年纪念徽章
日期:2011-11-01 16:23:26
3#
 楼主| 发表于 2008-11-18 15:49 | 只看该作者
这是一个模拟取列车席位的程序。
它通过 SRM(Struct Relational Map)技术实现数据库封装。

老板要求应用程序不允许出现SQL语句。
现在基本屏蔽了,还有一个where的小尾巴,可以在应用层写一个DAO(DATA access OBJECT)来解决。

有对数据库应用包装感兴趣的吗?一起讨论一下。

[ 本帖最后由 yulihua49 于 2008-11-18 15:52 编辑 ]

使用道具 举报

回复
论坛徽章:
14
2009新春纪念徽章
日期:2009-01-04 14:52:28沸羊羊
日期:2015-03-04 14:51:52优秀写手
日期:2014-03-14 06:00:13马上有房
日期:2014-02-18 16:42:022014年新春福章
日期:2014-02-18 16:42:022013年新春福章
日期:2013-02-25 14:51:24ITPUB 11周年纪念徽章
日期:2012-10-09 18:08:15蜘蛛蛋
日期:2012-06-27 21:08:142012新春纪念徽章
日期:2012-01-04 11:53:29ITPUB十周年纪念徽章
日期:2011-11-01 16:23:26
4#
 楼主| 发表于 2008-11-18 15:56 | 只看该作者

DTO.h,看看DTO的功能:

/* DTO=Data Transfer Object
        2008-11-18 by ylh */


#ifndef DTODEF

#define DTODEF
#define SERVER
#include <SRM.h>

typedef struct {
        SRM srm; //SRM=Struct Relational Map
        T_SQL_Connect *SQL_Connect;
        int             cursor;
} DTO;
/********************************************
* 初始化DTO,关联数据库和record
* SQL_Connect是数据库句柄,里边有OCI句柄
* T_PkgType是SRM模板,如果没有,可放null,将自动生成,稍稍费一点时间。
********************************************/
int DTO_init(DTO *DP,T_SQL_Connect *SQL_Connect,char *tabname,void *record,T_PkgType *tp);

//msg 用于生成SQL语句和返回错误信息
int DTO_insert(DTO *DP,char *msg);

//where是where子句,同时利用这个空间生成完整的SQL语句
//如果已经是update开头的,就直接利用,不生成了
int DTO_update(DTO *DP,char *where);

//where是where子句,同时利用这个空间生成完整的SQL语句
//如果已经是update开头的,就直接利用,不生成了
int DTO_update(DTO *DP,char *where);

//where是where子句,同时利用这个空间生成完整的SQL语句
//如果已经是delete开头的,就直接利用,不生成了
int DTO_delete(DTO *DP,char *where);
/****************************************************
* 调用select语句,
* where是where子句,同时利用这个空间生成完整的SQL语句
* 如果已经是select开头的,就直接利用,不生成了
****************************************************/
int DTO_get1(DTO *DP,char *where,int rownum);

/*****************************************************
* 以游标方式打开结果集
* where 用于生成语句, 还要利用这个空间生成完整的SQL语句
* 同时也是存放Fetch结果集的buffer
* 如果已经是select开头的,就直接利用,不生成了
****************************************************/
int DTO_prepare(DTO *DP,char *where);

//取结果集里的下一条记录,成功返回0
//能够自动识别DTO是select的还是prepare的
int DTO_next(DTO *DP);
/*********************************************
* 多表的select
* where是where子句,同时利用这个空间生成完整的SQL语句
* 如果已经是select开头的,就直接利用,不生成了
*********************************************/
int DTO_getm(int n,DTO *DP[],char *where,int rownum);

//多表的select, 取结果集里的下一条记录,成功返回0
int DTO_nextm(int n,DTO *DP[]);

//释放DTO,在游标状态下关闭游标
void DTO_free(DTO *DP);
#define  DTO_freem(DP) DTO_free(DP[0])

#endif

[ 本帖最后由 yulihua49 于 2008-11-18 16:23 编辑 ]

使用道具 举报

回复
论坛徽章:
14
2009新春纪念徽章
日期:2009-01-04 14:52:28沸羊羊
日期:2015-03-04 14:51:52优秀写手
日期:2014-03-14 06:00:13马上有房
日期:2014-02-18 16:42:022014年新春福章
日期:2014-02-18 16:42:022013年新春福章
日期:2013-02-25 14:51:24ITPUB 11周年纪念徽章
日期:2012-10-09 18:08:15蜘蛛蛋
日期:2012-06-27 21:08:142012新春纪念徽章
日期:2012-01-04 11:53:29ITPUB十周年纪念徽章
日期:2011-11-01 16:23:26
5#
 楼主| 发表于 2008-11-18 16:22 | 只看该作者
现在大家都喜欢Hibernate的啊,要写优雅的数据库持久化啊。
现在,我的C程序员可以只写应用逻辑啦,不必关心SQL,只要知道这20来个函数就行了。

以前那种 应用逻辑的小草淹没在访问逻辑的森林里的情况改善多了。

[ 本帖最后由 yulihua49 于 2008-11-18 16:26 编辑 ]

使用道具 举报

回复
论坛徽章:
27
参与WIN7挑战赛纪念
日期:2009-11-06 16:05:25ITPUB元老
日期:2011-04-23 17:54:35ITPUB十周年纪念徽章
日期:2011-11-01 16:24:04奥迪
日期:2013-08-05 09:30:132015年新春福章
日期:2015-03-02 10:21:23弗兰奇
日期:2016-12-28 13:54:54
6#
发表于 2008-11-18 17:04 | 只看该作者
看不懂、、、、

使用道具 举报

回复
论坛徽章:
14
2009新春纪念徽章
日期:2009-01-04 14:52:28沸羊羊
日期:2015-03-04 14:51:52优秀写手
日期:2014-03-14 06:00:13马上有房
日期:2014-02-18 16:42:022014年新春福章
日期:2014-02-18 16:42:022013年新春福章
日期:2013-02-25 14:51:24ITPUB 11周年纪念徽章
日期:2012-10-09 18:08:15蜘蛛蛋
日期:2012-06-27 21:08:142012新春纪念徽章
日期:2012-01-04 11:53:29ITPUB十周年纪念徽章
日期:2011-11-01 16:23:26
7#
 楼主| 发表于 2008-11-18 17:51 | 只看该作者
原帖由 erpmeng 于 2008-11-18 17:04 发表
看不懂、、、、

嗯,我得想想办法怎样让人看懂,首先你得会C语言。
应该了解这是个应用逻辑。要用到数据库,可是不想写SQL语句。
那就让DTO自动生成SQL语句,可是where还是要自己写的。
你要在init时提供表名,它会在数据库中自动查找表结构,自动生成各种SQL语句。你可以在程序的注释中看到DTO生成的语句。
一切以DTO开头的都是我写的,根据参数应该能猜出来干什么的。
最后的头文件,应该能看到各种函数的功能。

T_PkgType 是数据模板,现在并没有告诉你什么样子,你只需要知道他是解析C语言的struct用的就行了。
如果init时能够提供,就可以减少一次读数据库,不能提供就空着。

这个东西是写高性能应用服务器用的。有时JAVA服务器不能承受大的吞吐量,C服务器还是必要的。
它为C语言解决 ORM (Oject Relational Map)问题。

[ 本帖最后由 yulihua49 于 2008-11-18 17:58 编辑 ]

使用道具 举报

回复
论坛徽章:
1088
金色在线徽章
日期:2007-04-25 04:02:08金色在线徽章
日期:2007-06-29 04:02:43金色在线徽章
日期:2007-03-11 04:02:02在线时间
日期:2007-04-11 04:01:02在线时间
日期:2007-04-12 04:01:02在线时间
日期:2007-03-07 04:01:022008版在线时间
日期:2010-05-01 00:01:152008版在线时间
日期:2011-05-01 00:01:342008版在线时间
日期:2008-06-03 11:59:43ITPUB年度最佳技术原创精华奖
日期:2013-03-22 13:18:30
8#
发表于 2008-11-18 20:52 | 只看该作者
我们公司有自己做的产品,自动生成数据库的查询语句,c++写的,中间层是corba,客户端java

使用道具 举报

回复
论坛徽章:
519
奥运会纪念徽章:垒球
日期:2008-09-15 01:28:12生肖徽章2007版:鸡
日期:2008-11-17 23:40:58生肖徽章2007版:马
日期:2008-11-18 05:09:48数据库板块每日发贴之星
日期:2008-11-29 01:01:02数据库板块每日发贴之星
日期:2008-12-05 01:01:03生肖徽章2007版:虎
日期:2008-12-10 07:47:462009新春纪念徽章
日期:2009-01-04 14:52:28数据库板块每日发贴之星
日期:2009-02-08 01:01:03生肖徽章2007版:蛇
日期:2009-03-09 22:18:532009日食纪念
日期:2009-07-22 09:30:00
9#
发表于 2008-11-19 00:04 | 只看该作者
恕我直言,大部分自动产生的SQL都是垃圾,没办法作复杂的连接。另外你的方法没有用到绑定变量,这是一个大问题。
应用逻辑就不应该让C程序来写,应该写在存储过程。

使用道具 举报

回复
论坛徽章:
14
2009新春纪念徽章
日期:2009-01-04 14:52:28沸羊羊
日期:2015-03-04 14:51:52优秀写手
日期:2014-03-14 06:00:13马上有房
日期:2014-02-18 16:42:022014年新春福章
日期:2014-02-18 16:42:022013年新春福章
日期:2013-02-25 14:51:24ITPUB 11周年纪念徽章
日期:2012-10-09 18:08:15蜘蛛蛋
日期:2012-06-27 21:08:142012新春纪念徽章
日期:2012-01-04 11:53:29ITPUB十周年纪念徽章
日期:2011-11-01 16:23:26
10#
 楼主| 发表于 2008-11-20 09:13 | 只看该作者
原帖由 newkid 于 2008-11-19 00:04 发表
恕我直言,大部分自动产生的SQL都是垃圾,没办法作复杂的连接。另外你的方法没有用到绑定变量,这是一个大问题。
应用逻辑就不应该让C程序来写,应该写在存储过程。

你没注意,这个系统是绑定了变量的,不过在内部,可以通过DTO_getString()和DTO_setString()来存取,
当然也可以在DTO_init(&_DTO,SQL_Connect,&struct,T_PkgType *PARTTERN);
来手动绑定数据结构作为存取记录。这个模板和记录的关系见我的博客。
http://space.itpub.net/8804348/viewspace-478471
这样你就可以直接写结构了。就像hibernat给你POJO一样。

关于SQL,本系统也可以支持完全自己写,只要在where变量中写完整的SQL就可以了,有点像hibernate的HQL。

[ 本帖最后由 yulihua49 于 2008-11-20 09:18 编辑 ]

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 未成年人举报专区 
京ICP备16024965号-8  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表