JPA 为何如此难用,是我姿势不对吗

2021-02-10 11:44:17 +08:00
 XiLemon

RT,明天就过年了,我还在写 JPA 的东西,我快吐了。。。

声明:因为是第一次用,不熟悉,另外,个人认为是本人不理解 JPA 的设计思想,所以用起来很不顺手。

槽点:

  1. 多个条件,组合查询,当有些条件没有传参的时候怎么处理
    • 代码层面处理:用 specification 来处理,写起来好啰嗦,过于麻烦
    • @Query 注解,写原生 SQL 也挺恶心的
  2. 指定 update 条件
    应该不支持吧,只能用 @Query 注解写原生的 SQL,一旦字段比较多,而且部分可能为空的情况,写起来也是噩梦
  3. 多表关联查询
    JPA 不推荐多表关联查询?用起来也不够方便。

我是在用 MyBatis 的思路来用 JPA,完全不对路子。MyBaits 很灵活,在使用 JPA 的时候,感觉到处都是限制和不便。比如要用乐观锁,JPA 虽然有 @Version 注解处理,但是只能在 save 的时候才能用到。

用 MyBatis 感觉是在呼吸自由的新鲜空气,用 JPA 感觉是在地下室。。。

那么用 JPA 的朋友,是真的不需要灵活性,从业务设计上就完全解决了这些情况么。

本帖带有强烈的个人主观印象,用词如有冒犯到 JPA 用户,请强势打脸,教我做人!

打工人,打工魂,打工人是人下人 o(╥﹏╥)o

提前祝大家新年快乐!

8414 次点击
所在节点    Java
61 条回复
lewis89
2021-02-10 11:58:15 +08:00
ORM 就是 深陷泥潭的越南战场,任何试图从 SQL 到 Modeling 找一层简易或者容易理解的抽象 都是在做无用功
lewis89
2021-02-10 11:59:43 +08:00
理想的弗洛伊曼体系是 不存在硬盘这种低速随机读写存储社保..
sheeta
2021-02-10 12:08:08 +08:00
用过最舒服的还是 laravel 的 orm
frandy
2021-02-10 12:18:45 +08:00
1.1 、复杂条件语句可以试试引入 querydsl
1.2 、简单的一般直接 findby 自动生成,不需要设计到原生 sql
2.1 、不知道支不支持,生产中我们是直接从数据库中获取对象,然后赋值更新。
3.1 、杜绝表关联,两个表如果有关联的在业务层面拼接后返回给前端。
JPA 在 sql 优化上很麻烦,比如一条复杂语句,dba 检测到某个语句性能有问题,你排查起来不能很直观的根据原生 SQL 去找。优点也是这个,你没必要关注原生 SQL,不懂数据库的都能写。
目前新的项目,如果规模很大的,转到 MyBatis Plus 了,小规模的项目用 JPA 真的爽。
XiLemon
2021-02-10 12:55:32 +08:00
@lewis89 #1 此刻只想要灵活了
@sheeta #3 没写过 PHP 额
@frandy #4 2.1 每次都要 select 一遍,然后再 update 么,这也太麻烦了。。。 还是 MyBatis 舒服
frandy
2021-02-10 13:04:08 +08:00
@XiLemon #5 是的,原生只要一句话,基于 orm 的话,就得两句话了。
Vedar
2021-02-10 13:06:48 +08:00
主要是 java dsl 能力太弱了 jpa 这搞法真的是双重打击 将 java 的弱点发挥到极致了 还自以为很优雅
Leviathann
2021-02-10 13:25:40 +08:00
我们的后台管理+内部 crm 系统用的 jpa
单表简单查询用 findby
联表或者 n 多条件筛选可传可不传的都用自己封装的 query builder
Leviathann
2021-02-10 13:26:45 +08:00
update 的话都是用 java 代码做的
先 find 再 save
XiLemon
2021-02-10 13:27:22 +08:00
XiLemon
2021-02-10 13:32:15 +08:00
@Leviathann 单表的 CRUD,感觉还行,但是这一点 MyBatis 也能做到。但是多表关联查询以及写原生的内容 SQL JPA 的支持可太弱了

比如有些条件更新:update tb set a ..., status = ? where id = ? and status = ? 这种 update 语句,JPA 就无能为力了
lawler
2021-02-10 13:37:19 +08:00
mybaits 是 java 和 sql 隔离层,你清楚的知道,你在写 java 和 sql 。
JPA 是整体,忘记你在操作数据库,然后用面向对象方式对属性写逻辑描述。

1,多条件组合查询。 [不需要 sql]
findByStatusAndUpdateTimeBefore(String status, Date date);
findFirstByStatusAndIdNotInOrderByUpdateTimeDesc(String status, List<String> ids);
findFirstByStatusOrderByUpdateTimeDesc(String status);

2,指定条件删除 [更新同理,不需要 sql]
removeByCreateTimeBefore(Date updateTime);
removeByNamespace(String namespace);

3,多表关联查询。 [注解和 sql 条件]
@OneToMany(fetch=FetchType.LAZY, mappedBy="user")
@BatchSize(size=10)
@Where(clause="DEL_FLAG=1")
@OrderBy(clause="CREATED_DATE asc")
Kirsk
2021-02-10 13:37:29 +08:00
spring jpa 是根据 jpa 规范来实现的 本来思路就是不一样一个以对象建模 一个以数据库 SQL 用 mybatis 连表也强不到哪去 都一样是写 SQL
FightForFreedom
2021-02-10 13:45:36 +08:00
jpa 的话 update 可以的吧,虽然要加个 @Modifying 注解
XiLemon
2021-02-10 13:55:58 +08:00
@lawler #12 1. 用 findXxx 的方式查询的都是固定的。如果说有多个查询条件:a & b & c,当 b 不存在是,去掉它,用 a & c 这两个条件来查询。
2. remove 是物理删除么?通常业务做法是逻辑删除。update 同理指的是有这儿 updatXxxx 的接口方法么,IDEA 上没有这种提示额,能具体说一下嘛
3. 在 Entity 上写注解来关联查询,很麻烦呀。MyBatis 也支持在 Mapper.xml 中配置 Collection 来进行关联查询。这两种方式都很麻烦,而且比较固定,不够灵活。但是 MyBatis 能用原生 SQL 解决掉这些问题

整体上来进,JPA 的原则是不用 SQL,只操作实体类。可我没遇见过能完全不依赖 SQL 的场景,所以在原生 SQL 的支持上,JPA 的体验很烂。MyBatis 属于半自动化的 ORM 框架,在单表查询上没有比 JPA 繁琐多少,在灵活性上远胜 JPA 。MyBatis Plus 又弥补了单表查询不在便捷的缺点。
XiLemon
2021-02-10 14:00:50 +08:00
@lawler #12 @Where(clause="DEL_FLAG=1") 这个应该是逻辑删除的用法了
@Kirsk #13 我觉得 MyBatis 让我可以选,JPA 只能用它那一套了。两个框架( JPA 是规范,暂时代表实现 JPA 规范的框架)思路确实不一样。我比较好奇的时候,您在实际业务场景中,不会依赖原生 SQL 么?
@FightForFreedom #14 嗯,这个我知道,就是不够灵活。
lawler
2021-02-10 14:07:37 +08:00
@XiLemon #15
1. 使用 Specification 进行查询条件封装。和 mybaits 写 xml 一样。
我接触的 jpa 项目都不允许都这么复杂的设计,不利于维护,如果需要会进行评估。

2. 更新是 save 方法,自己操作对象进行更新。

3.无解。 如果不是报表系统,一般也不会进行多表关联查询的。极端需要性能的,干嘛不直接上 jdbc 呢。
cgpiao
2021-02-10 14:19:15 +08:00
ruby active record
业务类开发用 java 有些遭罪,用脚本语言吧。
XiLemon
2021-02-10 14:19:29 +08:00
@lawler #17 目前是用 Specification 来做的,感觉这个用起来足够啰嗦了,准备春节的时候看下 QueryDSL 会不会简洁一点。其实逻辑不算很复杂,没有超过 3 张表的关联,一般关联查询也就是两张表了。如果用 MyBatis 的话,能很快做完需求。
XiLemon
2021-02-10 14:21:18 +08:00
@cgpiao #18 -_-|| 打工人,公司项目用啥,我用啥呀。而且是在已有项目做的需求,没得选额,不然 MyBaits 一把梭,就不会有这个帖子了。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/752786

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX