业务逻辑是放在 Java 好还是放在 sql 好? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
zw1one
V2EX    问与答

业务逻辑是放在 Java 好还是放在 sql 好?

  •  1
     
  •   zw1one 2019-03-22 16:19:06 +08:00 8005 次点击
    这是一个创建于 2395 天前的主题,其中的信息可能已经有所发展或是发生改变。
    如题~
    第 1 条附言    2019-03-23 09:26:44 +08:00
    看了大家说这么多,我总结一下啊。

    1. 业务逻辑尽量放 java 里,除非对性能要求比较高,不愿意浪费与数据库交互的响应时间,就写存储过程。
    2. 存储过程相比 java 代码不好调试,不好维护,不易于迁移。
    3. 传统行业的软件开发更偏向于使用存储过程(这一点是瞎猜的)。
    60 条回复    2019-03-23 13:37:41 +08:00
    lueffy
        1
    lueffy  
       2019-03-22 16:22:56 +08:00
    代码里吧
    jay0726
        2
    jay0726  
       2019-03-22 16:23:25 +08:00
    业务逻辑放 sql 是什么操作?没见过啊,恕我孤陋寡闻了,告辞。
    leonme
        3
    leonme  
       2019-03-22 16:24:35 +08:00 via Android
    业务逻辑能放在 sql 里的一定是高手~ 2333
    SilencerL
        4
    SilencerL  
       2019-03-22 16:30:05 +08:00   1
    @leonme #3
    @jay0726 #2
    你们是没见到大部分业务逻辑全放在存储过程里面的
    每次加新功能或者 Debug 的时候我都要由衷问候上一任开发者全家的那种
    maxiaofeng
        5
    maxiaofeng  
       2019-03-22 16:32:09 +08:00
    sql 中写业务,除了你自己,别人是没有办法维护的。 数据库的压力也要考虑
    zw1one
        6
    zw1one  
    OP
       2019-03-22 16:32:11 +08:00
    @jay0726 比如说我要查三个表然后做一些处理,再把处理结果展示。我查了三次数据库,然后用 java 处理。这时候有人告诉我说,我这么查数据库是很浪费资源的,直接一个复杂的关联 sql 把业务处理了,说就应该这么写。
    xbigfat
        7
    xbigfat  
       2019-03-22 16:32:15 +08:00
    我认为放在 sql 里面好一些,相对的查询速度快,不用暴露 sql 到程序中去,对于客户端软件大有益处。我现在写的很多都是 PLSQL 里面的,有问题也好改,不用重新更新客户端
    lueffy
        8
    lueffy  
       2019-03-22 16:33:14 +08:00
    @SilencerL 我们公司直接规定 不准用触发器 /存储过程 /视图 外键约束都不让用
    连物理删除的权限都没有
    night98
        9
    night98  
       2019-03-22 16:34:58 +08:00 via Android   4
    @xbigfat 第一次见到 2019 年还有客户端直连 db 的。。
    xbigfat
        10
    xbigfat  
       2019-03-22 16:36:35 +08:00
    其实,好像 oracle 官方也是建议这么做的,在 plsql 的说明里面,写了不少这样做的好处

    >https://docs.oracle.com/cd/E11882_01/appdev.112/e25519/overview.htm#LNPLS0121
    xbigfat
        11
    xbigfat  
       2019-03-22 16:38:59 +08:00   1
    @night98 呃,我不是这个意思,我的意思是,总有一部分的 SQL 代码要暴露出来,通过写入数据库的方式,所有的逻辑都在数据库中,库外的程序只要填参数
    whypool
        12
    whypool  
       2019-03-22 16:47:13 +08:00
    以前很喜欢这样写,直接调用存储过程
    都是 sql 可以直接部到每个环境,还能用版本控制

    但是,后来,自己写的存储过程都要看很久才能明白业务逻辑

    数据库写业务真的难维护,注释写得再详细,都没程序代码好理解,能不用最好不用吧
    wysnylc
        13
    wysnylc  
       2019-03-22 16:47:59 +08:00
    十年前,随你怎么写
    现在,你写 sql 就是找骂,而且不仅别人骂,未来的自己也会骂现在的你煞笔
    domty
        14
    domty  
       2019-03-22 16:49:46 +08:00
    写程序里
    等你业务量起来了需要做水平扩展的时候 接中间件就可以了
    lookatme
        15
    lookatme  
       2019-03-22 16:52:07 +08:00
    题目里都带上 java 了,那基本上会遇到的所有场景都不应该把逻辑放在 sql 里
    felixcode
        16
    felixcode  
       2019-03-22 16:53:00 +08:00
    不熟悉存储过程不代表这不是最佳实践吧?
    存储过程还是有很多优势的。
    zhang77555
        17
    zhang77555  
       2019-03-22 17:37:09 +08:00
    复杂的业务逻辑还是写代码里把,简单的如果 XXX 则 XXX 这种,所有 sql 模板引擎都支持。能关联表出结果的时候一般关联表更好,不推荐使用存储过程,因为代码里不可见,问题追踪起来比较麻烦。
    karllynn
        18
    karllynn  
       2019-03-22 17:41:40 +08:00
    存储过程维护成本比代码高多了…难以理解,而且 debug 很麻烦
    l00t
        19
    l00t  
       2019-03-22 17:51:30 +08:00
    看情况吧。放存储过程里不利于水平扩展,但是没有水平扩展的需求的话,放存储过程里也没啥问题。另外就是也要看数据库,有些数据库本身不太行,那么塞太多东西也会影响表现。

    维护成本?一点也不高啊。存储过程这东西不是一目了然的嘛,哪有那么难读。
    huangdayu
        20
    huangdayu  
       2019-03-22 18:07:22 +08:00
    都是大佬
    xipushi
        21
    xipushi  
       2019-03-22 19:18:45 +08:00 via iPhone
    怎么爽怎么来
    jamesxu
        22
    jamesxu  
       2019-03-22 19:54:46 +08:00 via iPhone
    之前有外包把很多逻辑扔 oracle 存储过程、触发器、定时任务里,到处乱放,乱七八糟,我反向查问题得从一个库跳到另个库,从一个表跳到另一个表,从各种存储过程和触发器中跳转,简直了
    murmur
        23
    murmur  
       2019-03-22 20:01:25 +08:00
    @jay0726 所谓的热部署 业务逻辑放 SQL 上直接换存储过程就可以了 我还真见过这么玩的
    Kylinsun
        24
    Kylinsun  
       2019-03-22 20:24:23 +08:00 via iPhone
    sevice 层
    Xbluer
        25
    Xbluer  
       2019-03-22 20:50:17 +08:00
    @l00t 存储过程真不能算是一目了然。见过一些项目,3-4 千行起步,1 万行以上的比比皆是。有时候 IF 语句之后,隔了几百上千行之后才会见到对应的 else。。。
    Xbluer
        26
    Xbluer  
       2019-03-22 20:54:12 +08:00
    楼主可以了解下领域模型设计相关的东东。

    代码不应该仅仅实现业务逻辑;代码本身更应该完整的表达出对应的业务逻辑,SQL 语句本身并不具备次功能。
    billlee
        27
    billlee  
       2019-03-22 21:36:45 +08:00
    首先,你用的是什么数据库?
    silentstorm
        28
    silentstorm  
       2019-03-22 22:39:17 +08:00 via Android
    复杂业务还是 java 写比较好,但是简单不影响性能的表关联还是 sql 实现吧
    ebony0319
        29
    ebony0319  
       2019-03-22 22:54:32 +08:00
    写在代码里面。把公共方法写成一个公共服务层。我见过太多项目复杂业务直接写在 sql 的。这样有不好的地方:
    1 不方便调试,找出一个错误的地方太难了。
    2 维护成本太高,除了你估计别人也很难看懂。
    3.数据业务逻辑层不需要关心数据底层是什么数据库,你有可能目前是 mysql,Oracle,es,nosql。
    之前学 sql 的时候说的是存储过程运行快,安全,减少网络流量带宽...这些我觉得都可以找到相应的解决方案,并且现在硬件有了这么大提升。
    dudor
        30
    dudor  
       2019-03-22 22:56:12 +08:00
    我公司的业务大部分都是存储过程里写
    Imr
        31
    Imr  
       2019-03-22 22:59:57 +08:00 via iPhone   1
    @zw1one 做运维的告诉你,数据库是架构里最薄弱的一块,规模大起来,数据库瓶颈来的最快,而且升级最贵,相反扩展最便宜最简单的是后端跑的小机器。把大小操作都扔给数据库不是长远之计
    lijbgo
        32
    lijbgo  
       2019-03-22 23:10:30 +08:00
    我的原则是
    尽量都在 java 里写。
    特殊情况,为了性能,把部分代码写到数据库
    1.在 Java 里写会频繁调用数据库
    2.数据库返回大量数据,还需要在 java 中过滤
    l8g
        33
    l8g  
       2019-03-22 23:44:08 +08:00 via iPhone
    业务写在代码里 SQL 尽量简单
    bit
        34
    bit  
       2019-03-23 00:03:20 +08:00
    Oracle 官方低代码开发工具 Oracle Application Express (APEX) 请了解一下
    https://apex.oracle.com

    免费在线空间申请试用 (有中文版)
    https://apex.oracle.com/pls/apex/f?p=4550

    中国开发者微信群请搜索:APEX 中文社区微信群
    zjj19950716
        35
    zjj19950716  
       2019-03-23 00:59:49 +08:00 via iPhone
    刚接手一个项目,业务全在存储里,java 只负责选择存储,调用,取结果返回
    CallMeReznov
        36
    CallMeReznov  
       2019-03-23 01:20:08 +08:00   1
    把逻辑写到数据库里?
    那不就是存储过程吗
    第一个炸的就是这块
    anyele
        37
    anyele  
       2019-03-23 02:14:18 +08:00 via Android
    @xbigfat 如何单元测试
    herebury
        38
    herebury  
       2019-03-23 02:24:06 +08:00 via Android
    现在一般都写 Java 里了吧

    当年接手一个金融方面的 data warehouse,从数据库设计就让人震惊,业务全在存储里,各种 hard coded 数字,那叫一个看不懂,文档小字 400 多页,一队人啃完了依然不敢重构
    不过后来接了些其他的金融方面的项目发现数据库设计都很神奇,而且蜜汁健壮,反倒开始觉得 relational db 就该那么用了,贼可怕
    anyele
        39
    anyele  
       2019-03-23 02:32:35 +08:00 via Android
    无责任说一句,可能吼着互联网寒冬的,估计就是钟爱存储过程的那群人
    jingniao
        40
    jingniao  
       2019-03-23 05:59:26 +08:00 via Android
    前公司,金融类公司。
    业务核心全都存储过程,代码就是一个接入层。
    dexterzzz
        41
    dexterzzz  
       2019-03-23 08:15:54 +08:00 via Android
    金融,电信,医疗都是存储过程。
    wuzhi1234
        42
    wuzhi1234  
       2019-03-23 08:20:35 +08:00 via iPhone
    这种问题还有争议吗?肯定代码里啊
    1daydayde
        43
    1daydayde  
       2019-03-23 09:05:54 +08:00
    对于不需要维护的还是放 sql 里面吧
    beyond98
        44
    beyond98  
       2019-03-23 09:19:30 +08:00 via Android
    我们部门现在有个项目就是大部分逻辑都是在 sql 里,然后老大说要整改全部移到 java 里,目前改的人痛苦的想死(之前的 sql 是另一个人写的。。。)
    charlie21
        45
    charlie21  
       2019-03-23 09:25:50 +08:00 via iPhone
    如果用 spring 全家桶,难道没有这方面的惯例吗?(像 ror 的 ActiveRecord 专门处理连接数据库 )
    abcbuzhiming
        46
    abcbuzhiming  
       2019-03-23 09:39:01 +08:00   3
    这个问题 10 年前,在 ITeye 还叫 javaEye 的时候不就讨论过了吗?
    只有非常稳定的,基本不变动的业务,才适合放在存储过程里,因为存储过程的调试成本是非常高昂的,你去找个有经验的 DBA 试试。就算是有经验的 DBA,和有经验的码农放在一起,后者调试代码的成本也比前者调试 SQL 的成本低的多。所以只有像银行,医院,12306 这样的,业务成熟基本不变的地方,才会放存储过程。互联网这种需求一天 3 变的地方你业务放存储过程是嫌自己头铁加班加的少吗?
    另外还有一个历史原因,早年的数据库,本质是个操作系统,可以看一下当年 IBM 的盖世之作 IBM System R,DB2 的前身,看见人家叫什么(操作系统 R ),自身的性能,是可以把当年的应用层开发语言的性能吊起来打的,而且当年计算机硬件资源又很匮乏,哪像现在,阿猫阿狗随便买个云都是 4 核 8G 的,spring boot 架起来直接就能跑。当年那是“不得不一定要优化程序提升性能才能正常上线”。所以性能在当时比应用层语言强处很多的存储过程就自然落入了开发者的眼里了。
    现在,数据库很大程度上变成了数据仓库,搞分析有各种查询引擎,流处理,一般性查询业务应用层技术开发的很快,成本又低,JVM 优化了这么久,再加上硬件提起来后,大部分场合也吃的住了,存储过程这种开发调试代价高昂的东西,自然就边缘化了
    CasualYours
        47
    CasualYours  
       2019-03-23 09:43:55 +08:00 via Android
    @beyond98 哈哈,我刚好相反。老大是数据库出身,要把业务都存储过程实现,关键点是让我写他审,只能硬着头皮干了。
    ikaros
        48
    ikaros  
       2019-03-23 09:45:13 +08:00
    以前在一家金融公司就是放 sql 里,后来问一个熟人他在的金融公司也是这样的,看评论也是 推论 ====> 是不是金融公司都这样
    youthfire
        49
    youthfire  
       2019-03-23 09:47:25 +08:00 via iPhone
    作为外行,我犹豫过,“数据清洗和筛选逻辑是在 SQLite 里完成还是读取后用 Pandas 处理”。
    zw1one
        50
    zw1one  
    OP
       2019-03-23 09:53:20 +08:00 via Android
    @ikaros 是哪种金融公司呢?是自己做项目的互联网金融?还是向银行或大公司提供金融系统外包服务的公司?
    ikaros
        51
    ikaros  
       2019-03-23 10:41:21 +08:00
    @zw1one 自己做产品的
    wangxiaoaer
        52
    wangxiaoaer  
       2019-03-23 11:21:28 +08:00
    @night98 #9 啊 我孤陋寡闻了,客户端不直连 db 吗?
    cnbobolee
        53
    cnbobolee  
       2019-03-23 11:24:37 +08:00
    以前的 Oracle 和 db2 那些上古数据库很多不都是直接写存储过程的吗?
    levon
        54
    levon  
       2019-03-23 11:26:27 +08:00 via iPhone
    使用 orm 就是为了不写 sql
    abcbuzhiming
        55
    abcbuzhiming  
       2019-03-23 11:31:39 +08:00
    @ikaros 看什么类型的金融公司,传统金融公司的业务都已经固定了,追求的是两个方面,安全,对一致性要求相当高,算错一分钱都是大事;其次是性能,毕竟传统业务的客户数量也不低的,转账业务每天量也挺大,数据一致性问题,传统金融公司都是靠着单点机器性能硬顶(可能再过一二十年,NewSQL 才能慢慢的普及进去取代传统的 RDMS )所以相当依赖数据库事务,遵循严格的数据库设计范式,这种情况下,业务全放存储过程肯定安全的多啊,放代码层?请问你编程功力如何?能实现严格的事务逻辑吗?实现之后性能又如何?
    新的互联网金融公司都是靠着花里胡哨的业务骗钱的,今天一个活动明天一个促销,本质就是大街上卖吆喝,自然也就用互联网公司的方式了,业务都丢代码里,市场上的 Java 码农真便宜真香
    Telegram
        56
    Telegram  
       2019-03-23 12:33:13 +08:00 via iPhone
    @SilencerL #4 管家婆 erp,就是一大堆存储过程,二次开发一脸懵逼
    hilbertz
        57
    hilbertz  
       2019-03-23 12:43:54 +08:00
    你如果要强一致性,那只能放在数据库里
    xiaoxinshiwo
        58
    xiaoxinshiwo  
       2019-03-23 12:55:29 +08:00
    @zw1one #6 这么说的人都是浅视的,当你做业务拆分的时候就知道哪个好了
    superbai
        59
    superbai  
       2019-03-23 13:02:17 +08:00
    知道我今天为什么在加班么? 250 行的 SQL 真是太难调试了...
    Alexhohom
        60
    Alexhohom  
       2019-03-23 13:37:41 +08:00
    我司批量添加记录的操作就是直接用的存储过程,传极少参数就 ok 了,出错了还能回滚,实际使用体验不错
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2695 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 31ms UTC 02:27 PVG 10:27 LAX 19:27 JFK 22:27
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86