V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
ebony0319
V2EX  ›  Java

为什么我不喜欢 JPA

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

    比如根据标签找用户:

    表设计如下

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

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

    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[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-07-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 写起来方便,舍弃了这些,迎来的是多数据库的支持,以及高效的缓存(是不是真的高效,没测试过,官网是这样说的)
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1189 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 18:26 · PVG 02:26 · LAX 11:26 · JFK 14:26
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.