楼主: yulihua49

[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
21#
 楼主| 发表于 2008-11-21 16:48 | 只看该作者
// 再设计一个DAO,这个DAO就生成前面的语句。我看这个支离破碎的SQL比原来好懂,分别从列名表、表名、where进行分析。

int descDAO(DTO *DP,T_SQL_Connect *SQL_Connect,char *uTabname,PARTTERN_s *pp,char *stmt)
{
int ret;
char pattTable[256];
char DBOWN[49];

        // 如果是其它数据库,要改。
        strupper(uTabname);
        strcpy(DBOWN,SQL_Connect->DBOWN);
//这你大概能看懂点了,构建表名。
        sprintf(pattTable, "all_tab_columns c, "
                "(select table_name,column_name,position "
                 "from all_cons_columns "
                 "where owner='%s' and table_name='%s' and position is not null) k ",
                        DBOWN,uTabname);

//这个访问太特殊了,干脆DTO_init一起来。
        DTO_init(DP,SQL_Connect,pattTable, pp,PARTTERN_type);
        sprintf(stmt,"where c.table_name = k.table_name(+) "
                 "and c.column_name = k.column_name(+) "
                 "and c.owner = '%s' and c.table_name='%s' "
                 "order by c.table_name, c.column_id ",
                        DBOWN,uTabname);
        *SQL_Connect->DBOWN=0; //这是个小刁,访问系统表,避免语句生成器前缀DBOWN。
        ret=DTO_get1(DP,stmt,0);
        strcpy(SQL_Connect->DBOWN,DBOWN);//当然还要恢复。
        return ret;
}

对了,补充一点,我们不对变量进行绑定,
因为,1:如 where c.table_name=? and c.owner =? 这样的操作,经测试,速度反而慢(-1%),我也解释不了为什么。
2:我们没有语句池。3:将来DTO很可能不直接面对数据库,它要形成完整的语句,通过MQ传到服务器,服务器处理完再把结果集传回来,所以没法绑变量。可能这个服务器根本就不装数据库,也没有ODBC、JDBC这类东西。

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

使用道具 举报

回复
论坛徽章:
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
22#
 楼主| 发表于 2008-11-21 17:18 | 只看该作者
最后看看应用逻辑,有点长,耐心点。
你可以感到,你在专心致志的研究我如何生成模板(虽然看不明白,好些东西我没有交代),较少关心数据哪来的。

/********************************************************************
* 自动生成模板的程序
* 根据数据库表结构生成模板。需要一个辅助的表:PARTTERN_COL,
* 对数据结构进行补充定义,这个表可以不存在或空,表示没有补充和修正
* 如果对某表的某列有补充和修正,就在这个表中建立一条记录。
* 本程序适用于ORACLE
********************************************************************/

TABDESC *GetTable(T_SQL_Connect *SQL_Connect,char *tablename)
{
TABDESC *tabdesc;
char stmt[3024],tmp[1024];
int ret,n,i;
PARTTERN_s pattrec;
PARTTERN_COL_s upd_patt;
T_PkgType *tp;
struct td_node pk_node;
T_Tree *root=0;
DTO patt_DTO,upd_DTO;

        DTO_init(&upd_DTO,SQL_Connect,"PARTTERN_COL",&upd_patt,PARTTERN_COL_type);
        n=descDAO(&patt_DTO,SQL_Connect,tablename,&pattrec,stmt);
//ShowLog(5,"GetTable:%s.%s",SQL_Connect->DBOWN,tablename);
        if(n<=0) {
                ShowLog(1,"GetTable ret=%d:%s,err=%d,%s",n,stmt,
                        SQL_Connect->Errno,SQL_Connect->ErrMsg);
                DTO_free(&patt_DTO);
                return NULL;
        }
        tabdesc=(TABDESC *)malloc(sizeof(TABDESC));
        if(!tabdesc) {
                ShowLog(1,"TABDESC malloc Error!");
                DTO_free(&patt_DTO);
                 return NULL;
        }
        tp=tabdesc->tp;
        tp->offset=-1;
        tp->type=-1;
ShowLog(5,"GetTable %s colnum=%d",tablename,n);

        for(i=0;i<n;tp++,i++) {
                if(ret=DTO_next(&patt_DTO)) {
                        break;
                }
// 查找PARTTERN_COL表,修正模板
                ret=getUpdDAO(&upd_DTO,tablename,pattrec.Fld_Column_Name,tmp);
                //ret=0;
                if(ret==1) {
                        DTO_next(&upd_DTO);
                        if(!strcmp(upd_patt.COL_TYPE,"DELETE")) {//表示删除该列
                                DTO_free(&upd_DTO);
                                continue;
                        }
                        if(*upd_patt.COL_TYPE)
                                pattrec.Fld_Column_Type=mk_sdbc_type(upd_patt.COL_TYPE);
                        if(upd_patt.COL_LEN>0) {//修正该列的长度
                                pattrec.Fld_Column_Len=upd_patt.COL_LEN;
                        }
                        if(*upd_patt.COL_FORMAT) strcpy(pattrec.Fld_Format,upd_patt.COL_FORMAT);
                }
                DTO_free(&upd_DTO);
                     tp->name=strdup(pattrec.Fld_Column_Name);
                tp->type=pattrec.Fld_Column_Type;
                tp->len=pattrec.Fld_Column_Len;
                if(*pattrec.Fld_Format) {
                        tp->format=strdup(pattrec.Fld_Format);
                } else tp->format=0;
                if(pattrec.Fld_PK > 0) {
//ShowLog(5,"PARTTERN[%d]:%s,%d",i,pattrec.Fld_Column_Name,pattrec.Fld_PK);
                        pk_node.key=pattrec.Fld_PK;
                        strcpy(pk_node.colname,pattrec.Fld_Column_Name);
                        root=BB_Tree_Add(root,&pk_node,sizeof(pk_node),buf_Cmp,0);
                }
        }
/* 看看是否需要增加一个ROWID列 */
        ret=getUpdDAO(&upd_DTO,tablename,"ROWID",tmp);
        if(ret==1) {
                strcpy(pattrec.Fld_Column_Name,"ROWID");
                DTO_next(&upd_DTO);
                if(strcmp(upd_patt.COL_TYPE,"DELETE")) {//表示不删除该列
                        if(*upd_patt.COL_TYPE)
                                pattrec.Fld_Column_Type=mk_sdbc_type(upd_patt.COL_TYPE);
                        if(upd_patt.COL_LEN>0) {//修正该列的长度
                                pattrec.Fld_Column_Len=upd_patt.COL_LEN;
                        }
                        tp->name=strdup(pattrec.Fld_Column_Name);
                        tp->type=pattrec.Fld_Column_Type;
                                      tp->len=pattrec.Fld_Column_Len;
                        tp->format=0;
                        tp++;
                }
        }
        DTO_free(&patt_DTO);
        tp->type=-1;
        tp->len=0;
        tabdesc->colnum=set_offset(tabdesc->tp);
        tabdesc->rec=(char *)malloc(tabdesc->tp[tabdesc->colnum].offset+1);
        if(!tabdesc->rec||tabdesc->tp->type<0) {
                TabdescFree(tabdesc);
                ShowLog(1,"TABDESC->rec Malloc error!");
                if(root) BB_Tree_Free(&root,0);
                return NULL;
        }
        if(root) {
                        BB_Tree_Scan(root,mkpk);
                        BB_Tree_Free(&root,0);
                        ShowLog(5,"mkpk:%s",tabdesc->pks);
        }
        return tabdesc;
}

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

使用道具 举报

回复
招聘 : 数据库管理员
论坛徽章:
7
BLOG每日发帖之星
日期:2008-11-24 01:01:03BLOG每日发帖之星
日期:2009-01-20 01:01:05BLOG每日发帖之星
日期:2009-02-02 01:01:04BLOG每日发帖之星
日期:2009-03-27 01:01:10BLOG每日发帖之星
日期:2009-06-15 01:01:022010新春纪念徽章
日期:2010-03-01 11:08:29ITPUB十周年纪念徽章
日期:2011-11-01 16:20:28
23#
发表于 2008-11-21 17:18 | 只看该作者
建议楼主好好测试并发>100,及读写单表40个字段以上,数百万条记录的History表性能如何,
虽然我C语言远远比不上楼主,可是总有些担心这样做的性能

另外挑一个小刺,
SELECT  c.table_name,c.column_name,decode(data_type, 'CHAR',1, 'VARCHAR',1, 'VARCHAR2',1, 'DATE',129,'FLOAT',8, 'LONG',126, 'NUMBER',decode(nvl(DATA_SCALE,0),0, decode(nvl(data_precision,0), 0,257, 1,2, 2,2, 3,3, 4,4, 5,4, 6,4, 7,4, 8,4,9,4, 10,6, 11,6, 12,6, 13,6, 14,6, 15,6, 16,6, 17,6, 18,6, 257),8),257) Fld_Column_Type,decode(data_type, 'CHAR',data_length+1, 'VARCHAR',data_length+1,'VARCHAR2',data_length+1, 'DATE',20,'FLOAT',8,'LONG',-1, 'NUMBER', decode(nvl(DATA_SCALE,0),0,decode(nvl(data_precision,0), 0,35, 1,1, 2,1, 3,2, 4,4, 5,4, 6,4, 7,4, 8,4, 9,4, 10,8, 11,8, 12,8, 13,8, 14,8, 15,8, 16,8, 17,8, 18,8, 257),8),35) Fld_Column_Len,decode(data_type, 'CHAR',null, 'VARCHAR',null, 'VARCHAR2',null, 'DATE','YYYY-MM-DD HH24:MI:SS','FLOAT','%%lg','LONG',null, 'NUMBER',decode(nvl(DATA_SCALE,0),0,null,'%%'||to_char(data_precision+2)||'.'||to_char(DATA_SCALE)||'lf'),null) Fld_Format,k.position

FROM all_tab_columns c, (select table_name,column_name,position from all_cons_columns where owner='TICKET' and table_name='SEAT' and position is not null) k

where c.table_name = k.table_name(+) and c.column_name = k.column_name(+) and c.owner = 'TICKET' and c.table_name='SEAT' order by c.table_name, c.column_id

all_tab_columns 是oracle独有的视图,你这样做,如果数据库端换sqlserver,
这段模板代码得重写吧,实际上没有达到你老板要求的中间层可以使用任意数据库。

[ 本帖最后由 asword 于 2008-11-21 17:26 编辑 ]

使用道具 举报

回复
论坛徽章:
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
24#
 楼主| 发表于 2008-11-21 17:35 | 只看该作者
原帖由 asword 于 2008-11-21 17:18 发表
建议楼主好好测试并发>100,及读写单表40个字段以上,数百万条记录的History表性能如何,
虽然我C语言远远比不上楼主,可是总有些担心这样做的性能

另外挑一个小刺,
SELECT  c.table_name,c.column_name,decode(data_type, 'CHAR',1, 'VARCHAR',1, 'VARCHAR2',1, 'DATE',129,'FLOAT',8, 'LONG',126, 'NUMBER',decode(nvl(DATA_SCALE,0),0, decode(nvl(data_precision,0), 0,257, 1,2, 2,2, 3,3, 4,4, 5,4, 6,4, 7,4, 8,4,9,4, 10,6, 11,6, 12,6, 13,6, 14,6, 15,6, 16,6, 17,6, 18,6, 257),8),257) Fld_Column_Type,decode(data_type, 'CHAR',data_length+1, 'VARCHAR',data_length+1,'VARCHAR2',data_length+1, 'DATE',20,'FLOAT',8,'LONG',-1, 'NUMBER', decode(nvl(DATA_SCALE,0),0,decode(nvl(data_precision,0), 0,35, 1,1, 2,1, 3,2, 4,4, 5,4, 6,4, 7,4, 8,4, 9,4, 10,8, 11,8, 12,8, 13,8, 14,8, 15,8, 16,8, 17,8, 18,8, 257),8),35) Fld_Column_Len,decode(data_type, 'CHAR',null, 'VARCHAR',null, 'VARCHAR2',null, 'DATE','YYYY-MM-DD HH24:MI:SS','FLOAT','%%lg','LONG',null, 'NUMBER',decode(nvl(DATA_SCALE,0),0,null,'%%'||to_char(data_precision+2)||'.'||to_char(DATA_SCALE)||'lf'),null) Fld_Format,k.position

FROM all_tab_columns c, (select table_name,column_name,position from all_cons_columns where owner='TICKET' and table_name='SEAT' and position is not null) k

where c.table_name = k.table_name(+) and c.column_name = k.column_name(+) and c.owner = 'TICKET' and c.table_name='SEAT' order by c.table_name, c.column_id

all_tab_columns 是oracle独有的视图,你这样做,如果数据库端换sqlserver,
这段模板代码得重写吧,实际上没有达到你老板要求的中间层可以使用任意数据库。


放心吧,我们将来的表有上亿记录,数万终端争夺。没问题的,效率要比JDBC高。

现在的测试表有百万记录。当然没做那么多终端。不过当年的SRM系统,经过数百终端的考验,所以有把握。

DTO的底层是SDBC(安全数据库连接),诞生13年了,以安全、高效为宗旨,开发过很多项目,以快著称。
DTO没干什么,来回拷贝数据而已(数据传送对象),就是生成SQL,不过sprintf而已,没什么效率问题,
前边说了,每秒6万条的Fetch能力,包括DTO。

给你看看 DTO_next:

int DTO_next(DTO *DP)
{
int ret;

        if(!DP||!DP->srm.rec||!DP->srm.tp) return -1;
        if(DP->cursor<0) {
                if(!DP->srm.rp || !*DP->srm.rp) return -1;
                DP->srm.rp += net_dispack(DP->srm.rec,DP->srm.rp,DP->srm.tp);
                return 0;
        }
// DP是prepare的
        ret=___SQL_Fetch__(DP->SQL_Connect,DP->cursor,DP->srm.result);
        if(ret){
                sprintf(DP->srm.result,"DTO_next:err=%d,%s",
                        DP->SQL_Connect->Errno,
                        DP->SQL_Connect->ErrMsg);
                return ret;
        }
        net_dispack(DP->srm.rec,DP->srm.result,DP->srm.tp);
        return 0;
}
什么都没干,哪来效率问题?

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

使用道具 举报

回复
论坛徽章:
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
25#
 楼主| 发表于 2008-11-21 17:38 | 只看该作者
原帖由 asword 于 2008-11-21 17:18 发表
建议楼主好好测试并发>100,及读写单表40个字段以上,数百万条记录的History表性能如何,
虽然我C语言远远比不上楼主,可是总有些担心这样做的性能

另外挑一个小刺,
SELECT  c.table_name,c.column_name,decode(data_type, 'CHAR',1, 'VARCHAR',1, 'VARCHAR2',1, 'DATE',129,'FLOAT',8, 'LONG',126, 'NUMBER',decode(nvl(DATA_SCALE,0),0, decode(nvl(data_precision,0), 0,257, 1,2, 2,2, 3,3, 4,4, 5,4, 6,4, 7,4, 8,4,9,4, 10,6, 11,6, 12,6, 13,6, 14,6, 15,6, 16,6, 17,6, 18,6, 257),8),257) Fld_Column_Type,decode(data_type, 'CHAR',data_length+1, 'VARCHAR',data_length+1,'VARCHAR2',data_length+1, 'DATE',20,'FLOAT',8,'LONG',-1, 'NUMBER', decode(nvl(DATA_SCALE,0),0,decode(nvl(data_precision,0), 0,35, 1,1, 2,1, 3,2, 4,4, 5,4, 6,4, 7,4, 8,4, 9,4, 10,8, 11,8, 12,8, 13,8, 14,8, 15,8, 16,8, 17,8, 18,8, 257),8),35) Fld_Column_Len,decode(data_type, 'CHAR',null, 'VARCHAR',null, 'VARCHAR2',null, 'DATE','YYYY-MM-DD HH24:MI:SS','FLOAT','%%lg','LONG',null, 'NUMBER',decode(nvl(DATA_SCALE,0),0,null,'%%'||to_char(data_precision+2)||'.'||to_char(DATA_SCALE)||'lf'),null) Fld_Format,k.position

FROM all_tab_columns c, (select table_name,column_name,position from all_cons_columns where owner='TICKET' and table_name='SEAT' and position is not null) k

where c.table_name = k.table_name(+) and c.column_name = k.column_name(+) and c.owner = 'TICKET' and c.table_name='SEAT' order by c.table_name, c.column_id

all_tab_columns 是oracle独有的视图,你这样做,如果数据库端换sqlserver,
这段模板代码得重写吧,实际上没有达到你老板要求的中间层可以使用任意数据库。


是啊是啊,模板生成器每个数据库要单写的。我前边说了,换数据库,要换DTO里边的程序,要修理DAO,但是不换应用逻辑。

写这个DTO我用了2星期,刚写完,就分享了。

我将来要改进它,支持各种插件,更换底层换插件就行。

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

使用道具 举报

回复
论坛徽章:
520
奥运会纪念徽章:垒球
日期: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
26#
发表于 2008-11-22 00:23 | 只看该作者
以你自己的代码为例,getSeat_for_sell工作量占了大头。里面的代码像“if((xb%10)==0) { //软卧 硬卧的查询......ELSE.....”这分明就是业务逻辑,而不是什么数据访问逻辑。至于你说的剩下的“面向业务规则的那些东西”,基本上没有什么了,你说“使用这个DAO的程序会有很多,就不用一一修改了”我想像不出除了售票模块还有什么会用到getSeat_for_sell。在我看来它和getSeat_for_sell完全可以做到一层,你完全可以少维护一层程序。

哪一天业务需求变更,比方说在“始发日期、车次、上车站、下车站、席别、用途”之外再增加一个条件,那么你要改的地方就有两层,getSeat_for_sell是逃不掉的,业务逻辑与访问逻辑分离只是一种美好憧憬。

再来看你#21的复杂SQL。这是为你的中间层服务的,用静态SQL写业务逻辑就完全没有这些开销,包括#24的所谓“模板”,如果用存储过程就完全没有必要。
另外,你只需访问user_tab_columns, user_cons_columns 就无需理会OWNER是什么了;还有你有没有想到同一个列在all_cons_columns 中可能出现两次以上?这会导致你的连接产生重复数据。(后记:从其他代码看出你只是想知道该列是否为主键,那么可以连到USER_CONSTRAINTS并加上CONSTRAINT_TYPE = 'P'条件)


"1:如 where c.table_name=? and c.owner =? 这样的操作,经测试,速度反而慢(-1%),我也解释不了为什么。"
你用的什么测试用例?变量的取值有多少种?
table_name, owner都是相对“静态”的数据,厉害的是如 where user_id = ? 这样的,如果你有10万用户,用10万个变量和10万个常量试试!


"2:我们没有语句池。"
当然不用自己做了,数据库有啊!它替你管理了,而你却不愿意利用它!


"3:将来DTO很可能不直接面对数据库,它要形成完整的语句,通过MQ传到服务器,服务器处理完再把结果集传回来,所以没法绑变量。可能这个服务器根本就不装数据库,也没有ODBC、JDBC这类东西。"
本来直截了当的东西,你非得为它加上一层层包装,经过N层处理到达服务器,在服务端还原再包装再扔回来再还原……累不累啊。这种通用系统不用也罢,客户花钱买了ORACLE你却把它降级到和免费的山寨数据库等同的功能!

[ 本帖最后由 newkid 于 2008-11-22 03:42 编辑 ]

使用道具 举报

回复
论坛徽章:
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
27#
 楼主| 发表于 2008-11-23 14:41 | 只看该作者
我会认真考虑你的意见。非常需要负面的意见,有利于改进我们的系统。对这些宝贵意见表示感谢。
我还会继续发表这方面的话题,希望你继续积极发表意见。这个东西我是准备做一个开源项目的,也希望有兴趣者积极参加。
你提到的问题,我要做一些验证工作,稍后回答。

使用道具 举报

回复
论坛徽章:
0
28#
发表于 2008-11-23 16:15 | 只看该作者
不错,先收集一下;

使用道具 举报

回复
论坛徽章:
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
29#
 楼主| 发表于 2008-11-24 17:07 | 只看该作者
再来看你#21的复杂SQL。这是为你的中间层服务的,用静态SQL写业务逻辑就完全没有这些开销,包括#24的所谓“模板”,如果用存储过程就完全没有必要。

不是没必要,是办不到。
在C语言里,按照struct处理数据是劳动生产率最高的。
seatapp的最后是什么?占用席位当然不是目的,你要把占用的席位打包发送到客户端,我们的工程规定用JSON(JAVA SCRIPT OBJECT NOTATION)格式。怎么打?17个列,一个一个点?这么低级的工作,我怎么忍心让精通SQL的高级精英去做?!
于是,1楼的那句话你注意没有?
        DTO_toJSON(&seat_DTO,json,0);
一句话,一个row的数据打包完成!怎么样,劳动生产率一下至少提高17倍吧?
许多复杂的业务处理是需要动用函数的,函数间怎么传数据,当然是传一个结构要比传一大堆离散的变量要好得多。
SQL都是面向列的,怎么组装结构?一个一个列的点名吗?又让我们老板花高价聘的精英做低级劳动?老板亏死了!
数据结构变化了,怎么办?你必须把所有列名列表检查一遍:
prepare、fetch into、insert、update,以及所有的应用逻辑。
这使我们陷入痛苦的泥潭。
解决这个问题,JAVA早有办法:ORM(OBJECT RELATIONAL Mapping)。我们的办法更早:
SRM(Sruct Relational Mapping);不过那时不叫这个。
怎么Mapping?模板!Hibernate有 *.hbm.xml,ibatis 也是用XML。

注意26楼的一句话吗?
DP->srm.rp += net_dispack(DP->srm.rec,DP->srm.rp,DP->srm.tp);
把结果集DP->srm.rp用模板DP->srm.tp解析到用户结构DP->srm.rec。

就是说,DTO是基于SRM的,如果不用DTO,至少也要SRM。
这样,我们至少是有细胞生物,struct和object都是细胞,我们向无细胞生物的世界推销细胞的好处。

模板,可以手动建立,也可以自动建立,还可以使用时建立,就像1楼。

有了模板,程序员们不再关心所有的列,我给的seatapp的例子,只用到3个列。DAO里也只用到了where里的列。如果数据结构变化了,你没有修改程序,也出不了大乱子,如果修改了模板,那就万事大吉了,剩下的业务逻辑一般不会有多大调整,用到哪改到哪就是。所以,模板这个东西是一次定义多次使用,非常合算的一个东西。

就像铸模,做一个模子,你可以浇铸一百个、一千个产品,比起给你一个铁疙瘩,你锯、你锉、你凿,即使你是高级铁匠,能有什么生产率呢?师傅还非常自豪的说:我们根本不需要模子!

我们做的是流水线上的一个部件,他让工人变成傻瓜,只要会几个简单动作,就会生产出我们要的产品。这个部件的设置是需要精英来做的,设计数据结构、构建模板(不管是手工还是自动),提供DAO。剩下的,让工人做去吧,老板要的就是这个。

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

使用道具 举报

回复
论坛徽章:
1
蜘蛛蛋
日期:2011-07-08 14:41:18
30#
发表于 2008-11-24 21:30 | 只看该作者


什么东东??一点都看不懂哦。。

使用道具 举报

回复

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

本版积分规则 发表回复

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