|
呵呵,我说怎么找不见贴,原来置顶了。关于C或JAVA的各种FRAMEWORK的讨论超出我的范围,我就说几句外行话,如果不对请指正。
"于是,1楼的那句话你注意没有?
DTO_toJSON(&seat_DTO,json,0);
一句话,一个row的数据打包完成!怎么样,劳动生产率一下至少提高17倍吧?"
1楼的这段程序,我觉得就应该是这样:
用start_date,Train_no,carno作输入参数,调用一个存储过程; (而不是你的组装stmt)
存储过程利用这些输入作DML或查询,最后输出一个结果集(或几个返回参数)(这就是我说的“业务逻辑”,我认为该用存储过程实现)
遍历这个结果集,该怎么用就怎么用。如果你还想传给前台的其他模块,又必须按规定包装成JSON或者什么,那完全是和业务无关的,属于数据的格式化,你愿意的话完全可以做一段通用程序(类似DTO_toJSON)去处理,或者用一段自动生成的代码去处理。
这些前台程序员,他们看到的是事务接口,而不用关心数据库端的实现。你也说了是由你们的精英来完成的,一般程序员何必知道里面有这个SEAT表?何必知道某个地方要用自动模板,另一地方就用手动模板?他们只需知道根据输入(来自用户或来自其他模块)可以得到想要的数据,这数据完全可能是从几个表通过复杂连接得到的;只需知道把输入喂给数据库,数据库就会用DML把数据写到该去的地方,可能是一个或多个表。
"许多复杂的业务处理是需要动用函数的,函数间怎么传数据,当然是传一个结构要比传一大堆离散的变量要好得多。"
如果采用我说的存储过程方式,复杂性屏蔽到数据库里了,前台模块间接口将会简化,层次也会少很多。当然你可以用你喜欢的方式在中间传递数据,到最里层再换成数据库能辨认的格式。
"SQL都是面向列的,怎么组装结构?一个一个列的点名吗?……"
当我们在PL/SQL DEVELOPER中查看一个输出结果集(游标)的时候,它会自动变成二维表的形式(组装结构),这不难做到吧?我只管写我的SQL, 输出什么就不用再去一个一个的点了。这就是我上面说的可以有“通用程序”来处理数据的格式化。
"数据结构变化了,怎么办?你必须把所有列名列表检查一遍:prepare、fetch into、insert、update,以及所有的应用逻辑。这使我们陷入痛苦的泥潭。"
我的建议是要在客户端程序消灭SQL, 全部放到存储过程中,仅留下事务接口。如果接口变了,那么调用的地方肯定要修改;如果只改动后台结构,那么只需修改存储过程(虽然这种情况并不多见)。
数据结构变了,存储过程中的DML(INSERT UPDATE等)要作相应修改,这在我看来并不痛苦。静态的SQL有它的好处:你可以在编译的时候就知道SQL有没有写错,你可以把它分离出来调优,如果哪个数据有错,你可以轻易跟踪到输入源头。一个事务涉及了什么表,数据从哪里来,怎么变化、怎么加工,用静态SQL看起来十分直观。这样的事务处理程序容易维护。
用你的方法,则是修改模板,在我看来并不比改写PL/SQL方便多少。如果是“使用时建立”的动态模板(利用数据库字典),那么你就等于自己多套一层,系统性能要打个折扣。
依赖模板的动态SQL, 调试调优就更加困难。你的DBA可能从后台找出性能不佳的SQL, 但这个SQL是从什么地方组装出来的?那可要费一翻脑筋,用SQL全文检索是找不到的。
"模板,可以手动建立,也可以自动建立,还可以使用时建立,就像1楼。"
不知道你的程序运行时候能否不依赖模板?我的看法是模板仅仅是用作开发的辅助工具,你可以用模板生成源代码,程序是脱离模板运行的。
"就像铸模,做一个模子,你可以浇铸一百个、一千个产品,比起给你一个铁疙瘩,你锯、你锉、你凿,即使你是高级铁匠,能有什么生产率呢?师傅还非常自豪的说:我们根本不需要模子!"
钟表匠不会浇铸出一个个齿轮然后交给你去组装。你最多就是装上电池,拧紧发条。至于钟表匠自己用什么模具?哪些部件可批量生产?原材料有几种?那就是钟表匠的事啦。
"我们做的是流水线上的一个部件,他让工人变成傻瓜,只要会几个简单动作,就会生产出我们要的产品。这个部件的设置是需要精英来做的,设计数据结构、构建模板(不管是手工还是自动),提供DAO。剩下的,让工人做去吧,老板要的就是这个。"
你的流水线在DAO, 我的流水线在数据库里。工人仅仅作UI的处理(收集输入数据,展示输出数据),当然他们也不能是傻瓜,这部分的编程也有技巧和讲究,但已经不属于事务处理范围了。
再来看看那天说的并发处理,你用SELECT ... for update WAIT 10 SKIP LOCKED确实不会出现重票的问题。但这里也有一个小问题,如果你开两个SESSION做如下测试:
SELECT * FROM SEAT WHERE FLAG=0 AND ROWNUM<2 for update WAIT 10 SKIP LOCKED;
第二个窗口其实会返回NO_DATA_FOUND, 它不会往下再找一条新记录去加锁。 |
|