为什么我不喜欢 JPA - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
ebony0319
V2EX    Java

为什么我不喜欢 JPA

  •  
  •   ebony0319 2019-07-03 23:46:58 +08:00 5686 次点击
    这是一个创建于 2295 天前的主题,其中的信息可能已经有所发展或是发生改变。
    • 第一我很蠢。
    • 第二 SQL 的世界是复杂的,而 JPA 是单纯的。

    比如根据标签找用户:

    表设计如下

    • 用户表
    • 用户标签表
    • 标签表

    sql 很好写(使用的是 postgresql):

    select c.id,c.username from client_customer c inner join client_cusom_and_label cl on c.id= cl.custom_id inner join client_label l on cl.label_id=l.id group by c.id having array_agg(l.id) @> array[65,67] 

    但是 jpa 里面:

    @Query(nativeQuery = true,value = "select c.id,c.username\n" + "from client_customer c\n" + "inner join client_custom_and_label cl on c.id= cl.custom_id\n" + "inner join client_label l on cl.label_id=l.id\n" + "group by c.id\n" + "having array_agg(l.id) @> array[:list]") List<Map<String,Object[]>> findByLabelId(@Param("list") List<Integer> list); 

    当 list 的 size 等于 1 的时候非常好写,但是大于 1 的时候自动加了括号 array[(?, ?, ?)]:

    Hibernate: select c.id,c.username from client_customer c inner join client_custom_and_label cl on c.id= cl.custom_id inner join client_label l on cl.label_id=l.id group by c.id having array_agg(l.id) @> array[(?, ?, ?)] 
    19 条回复    2019-08-05 16:55:55 +08:00
    skypyb
        1
    skypyb  
       2019-07-04 08:30:56 +08:00 via Android   1
    在不就在使用 jpa 的同时用下 JdbcTemplate 处理一些 jpa 不方便处理的 sql 得了 ...
    ebony0319
        2
    ebony0319  
    OP
       2019-07-04 08:51:36 +08:00
    @skypyb 谢谢老哥指明一条道路.
    br00k
        3
    br00k  
       2019-07-04 09:51:48 +08:00   1
    可以用 querydsl
    adzchao
        4
    adzchao  
       2019-07-04 10:03:42 +08:00   1
    @ebony0319 资深 jpa 使用者 给你几个建议 默认你的表结构 是逻辑关联 也就是单表
    1,简单单标操作可以使用 jpa
    2,多表可以使用 mybatis 或者使用 NativeQueryRepository

    如果你是关系表 那就直接 jpa 干吧 根本不需要写一条 sql
    efaun
        5
    efaun  
       2019-07-04 10:19:03 +08:00   1
    jpa 本来就不是为多表而生的
    ShuangChenyue
        6
    ShuangChenyue  
       2019-07-04 10:31:56 +08:00   1
    如果这种多表关联的 sql 多了或者用到了很多 sql 函数
    用 mybatis-plus 吧
    就我的感受而言 mybatis-plus 很爽 比 jpa 更适用
    ebony0319
        7
    ebony0319  
    OP
       2019-07-04 11:06:11 +08:00
    @ShuangChenyue 我也是这样觉得的,但是 CTO 技术选型的时候就只能用 JPA,其实很无奈.
    anakinsky
        8
    anakinsky  
       2019-07-04 11:11:22 +08:00   1
    nativeQuery 也不能映射自定义对象,很蛋疼
    Takamine
        9
    Takamine  
       2019-07-04 14:28:58 +08:00   1
    菜鸡表示自己撸的时候还是用的 mybatis,简单查询直接走注解,复杂的走 XML,工作就是全走 XML。
    zjsxwc
        10
    zjsxwc  
       2019-07-04 16:50:16 +08:00
    搞不懂为什么要多表级联,
    笛卡尔积下来性能会很差,
    楼主的例子还不如分 2 次单表查询,
    尽量避免复杂 sql 的好处了维护方便。
    mmdsun
        11
    mmdsun  
       2019-07-05 07:52:26 +08:00 via Android
    jpa 可以配置一对多啊。用 hql 写起来也很方便。而且方便迁移数据库
    1340976576
        12
    1340976576  
       2019-07-05 16:37:50 +08:00
    这种复杂查询建议使用 JPA+QueryDSL
    abcbuzhiming
        13
    abcbuzhiming  
       2019-7-08 20:54:59 +08:00   1
    @mmdsun 迁移数据库是伪命题,这已经不是数据库群雄争霸的时代了,你能遇上一次项目更换数据库,那简直可以去买彩票
    abcbuzhiming
        14
    abcbuzhiming  
       2019-07-08 21:03:03 +08:00   2
    jpa 最大的问题,不光是楼主说的“ SQL 是复杂的”。要我来说的话,JPA 上下不靠:

    1.该简单的时候简单不起来,你们去看看别的动态语言,尤其是 ActiveRecord 和链式调用的创始者 Ruby on Rail,是怎么处理单表查询的,是怎么用链式调用拼查询条件的。JPA 压根就做不到这么简单

    1.该复杂的时候恶心的要死,需要写原生 SQL 的场合 JPA 那个费劲,那个丑陋啊。。。

    根本原因在于,关系模型和对象模型是有区别的,老是有人生搬硬套想用对象模型去描述关系模型,也不想想这招要能成功的话,关系数据库不早就被对象数据库干掉了?

    Java 界的 Spring Data JPA 和.net 界 Entity Framework,都是上个时代面向对象思想到高峰时的典型产物,其实压根就不符合现在这个时代,Sql 现在越来越有生命力,想彻底屏蔽 sql 细节,别做梦了
    wc951
        15
    wc951  
       2019-07-09 09:53:51 +08:00 via Android
    @abcbuzhiming 你是没遇到通用中间件在不同项目里适配多种数据库的
    abcbuzhiming
        16
    abcbuzhiming  
       2019-07-09 11:00:50 +08:00
    @wc951 中间件的特点是距离业务有一定距离,不和业务直接关联,真要用到必须原生 sql 直接上的,都是和业务强相关,此时中间件就失灵了,中间件不能屏蔽 sql 的复杂度
    chihiro2014
        17
    chihiro2014  
       2019-07-10 00:15:24 +08:00
    JPA 基于类来进行查询,那种很方便。但是遇上复杂查询,还是 mybatis 更好
    SkyLine7
        18
    SkyLine7  
       2019-07-10 16:57:15 +08:00
    第一 jpa 也可以写 native sql
    第二 mybatis 不便于迁移
    nnnToTnnn
        19
    nnnToTnnn  
       2019-08-05 16:55:55 +08:00
    @ebony0319 e.....mmmm jpa 提取数据,逻辑用 Stream,肯定没有原生 sql 写起来方便,舍弃了这些,迎来的是多数据库的支持,以及高效的缓存(是不是真的高效,没测试过,官网是这样说的)
    /div>
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     982 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 25ms UTC 22:34 PVG 06:34 LAX 15:34 JFK 18:34
    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