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

提前祝大家新年快乐!

8459 次点击
所在节点    Java
61 条回复
Kirsk
2021-02-10 14:29:46 +08:00
@XiLemon 不会啊 我设计表原则都是对象加关系表 复杂场景可以多实体映射一张表 避免不需要的字段
huang7230468
2021-02-10 14:39:17 +08:00
个人见解:
1. JPA ( Java Persistence API )是外国定义的一套数据持久化规范的 API,像我们现在用的 Spring-Data-JPA 底层就是 JPA,但 Spring-Data-Mongo 就没有;而 Mybatis 是国人写过,是一套非常灵活的 ORM 框架;
2. JPA 是支持单表或者多表的,但多表是需要自己写 Native SQL ;而 JPA 其实推崇使用单表的,有点像国内现在推崇尽量减少 join 关键字,从减少数据库的压力(当然这里也是看业务场景,不是一味的盲从);
3.JPA 是从面向对象的角度设计的,减少 SQL 的硬编码,以减少后期的更换数据库的迁移成本;
4.JpaSpecification 的写法复杂度,其实是可以容忍的,因为稍微花点的时间,你会爱上他;

对于 JPA 需要改变以往的从数据库从发的设计,学会从业务建模的角度开始,可能会有更好的思路。目前我们已经用了几年,只会感觉越来越好用,越来越简单。
BBCCBB
2021-02-10 14:47:44 +08:00
@huang7230468 指正一下, mybatis 不是国人写的 🐶
winglight2016
2021-02-10 14:59:50 +08:00
不讲需求场景,没法比较吧。JPA 应该是偏向 OOP 的,一般的 CRUD 业务可以很方便地实现,从设计角度看,对象建模比数据库建模更容易表达业务需求,也不容易出错。mybatis 是面向 SQL 的,需要程序员非常了解表结构才能开发,而且需要重新做业务到 SQL 的映射,这个过程容易产生理解偏差。以上就是 JPA 的优势。

至于 JPA 在某些场景下的不便,lz 的说法看起来有一半是不熟悉这种 ORM 的思路导致的,另外一半,包括批量更新和复杂查询,这两个场景的确不适合使用 JPA 实现,个人会考虑使用异步任务和搜索引擎 /动态视图这样的方法来实现。在我看来,mybatis 和原生 sql 没有太大区别(设计角度看),所以仅仅是方便写代码的优势并不会让我选择它。
jaynos
2021-02-10 15:02:55 +08:00
没人觉得 mybatis 也很麻烦啰嗦么,xml 配置没有类型安全(指编译时检查)我就觉得很淦。

在后台一些场景(如一个商品列表,需要展示商品信息,店铺信息,收藏人数)在动态查询的时候 Specification 和 mybatis plus 都是啰啰嗦嗦几十行,不知道大家在这种场景下是怎么干的。。。
chocotan
2021-02-10 15:31:24 +08:00
我自己的项目用 jpa,公司的项目用 mybatis
用 mybatis 的思维去写 jpa 肯定是会遇到各种问题的
XiLemon
2021-02-10 15:49:37 +08:00
@huang7230468 #22 JpaSpecification 我真的爱不上啊,MyBatis Plus 是国产的,MyBatis 不是。另外,迁移数据库,以我有限的职业生涯来说,不知道会不会遇到,至少目前没有。我理解到了要迁移数据库的层面,可能重新写业务是更好的方式吧。
@winglight2016 #24 确实不熟悉,也不太理解这种思想。需要深入学习一下,请问有合适的资料可以推荐一下么
@jaynos #25 我觉得也还行啊,稍微有点啰嗦。
@chocotan #26 我也认为是思路有问题,但是实际上确实要用到原生 SQL 的功能。

问题来了,怎么掌握 JPA 的这种设计思想呢?
iamppz
2021-02-10 17:23:34 +08:00
目前是 JPA 、原生 SQL 混合使用,动态的部分交给原生 SQL 去处理,领域逻辑相关的部分交给 JPA 处理,代价就是需要花额外的时间去做兼容。其实 MyBatis 也有 MyBatis 的问题,不是有句老话叫「没有银弹」,没有任何一个框架能解决所有的问题。
wc951
2021-02-10 19:16:14 +08:00
因为你依然处在面向关系型数据库编程的思维方式,尝试阅读有关 DDD 、CQRS 之类的概念会有些帮助,还要考虑你的场景到底是属于 olap 还是 oltp
idoggy
2021-02-10 20:03:04 +08:00
mybatis 我现在也不手写 sql 了,需要手写的都能用 dsl 实现,实现不了硬要手写的就加开评审会好好梳理下逻辑
aguesuka
2021-02-10 20:47:28 +08:00
本质是 java 的类型系统无法为 sql 做静态检查。大家可以了解一下"依赖类型"这个概念。
等 java30 支持"dependent type"以后就会非常愉快了。

学术界已经有解决方案了

https://homotopytypetheory.org/2016/09/26/hottsql-proving-query-rewrites-with-univalent-sql-semantics/
hantsy
2021-02-10 21:28:42 +08:00
最好是找一本 JPA 方面的书籍系统的学习一下 JPA,推荐 Gaving King 的 Manning 出版的 Java Persistence with Hibernate, 或者 Apress 出版的 Pro JPA 2 。

想通过简单的 API 认识入门,用好 JPA 的可能性不大。早在 15 年前,国内很多使用 Spring,基本都是会配合使用 Hibernate,那时 Hibernate 官方文档是不可多得资料。现在能够静下心来看几百页文档(或者书籍)的年轻程序员太少。我常常看到一些国内的技术博客,看到别人某篇文章,自己依葫芦画飘的写一个 Hello World 程序就得出结论,Hibernate/JPA 这不行那不行。看到 JSF 的时候, 在某些人的眼里就是 JSP 一样,只是换换 tag 而已。

我面过很多自称非常熟悉的 Hibernate/JPA 的程序 ,连最基本的一级缓存(或者 Hibernate Session,或者 Persistence Context )中几种对象的状态(这是基础中的基础)的转换都说不上来。一个 Hibernate LazyInitialzationException 和 N+1 查询都是可以检测你是不是真正用到 Hibernate/JPA 。自称用过 JSF 的居然连基础的 request Lifecycle 都说不上来(更有甚者,没听说过)。

JPA 作为一套规范,完全使用 OOP 方式解决 Java Persistence 问题,使用 JPA 时完全可以忘记数据库的存在。最初是很好的解决了 ORM,而且仅针对 RDBMS, 但是随着 NoSQL 的流行,Hibernate OGM (使用 JPA 操作 NoSQL )新项目已经支持常见的 NoSQL 。可惜 NoSQL 天然操作上不如关系数据数丰富,有些 NoSQL 也宣称支持 SQL (也只是部分支持,使用上很多限制,比如 Cassandra )。

Eclipse 下 JNoSQL 项目会形成一套规范 API 操作 NoSQL,与 Jdbc 和 JPA 相似,分为高低两级 API,其高级的 API 与 JPA 极为类似,可能集成到下一代的 Java EE/Jakarta EE 10 标准中去。
hantsy
2021-02-10 21:41:36 +08:00
JPA Provider 目前几种:Hibernate (非常活跃),EclipseLinks 比较活跃,OpenJPA 不那活跃了。DataNucleus 最初是 JDO 标准的参考实现,后来扩展到支持一系列的标准,包括了 JPA 。 一般项目很少用,这个最初 Google 云上内置支持。

由于 Spring Boot 默认使用了 Hibernate 作为 JPA 实现,所以很多同学在不了解标准的情况,一上来就 Hiberante 和 JPA 混为一团。

JavaEE/Jakarta EE 开发一般依赖应用服务器默认使用哪种(当然大部分服务器的标准组件是可以换成其他的),EclipseLinks 和 Hibernate 比较常见。
Cbdy
2021-02-10 22:03:41 +08:00
JPA 是 Java 过度设计时代的产物,是 OO 狂热时产生的设计

倒也不是完全不能用,在一些小的场景有点用,但大多数时候还是建议写 SQL
onikage
2021-02-10 22:13:26 +08:00
和姿势没关系, 还是要看项目, 一些简单项目, 没几张表的, 表关系简单的, 用 jpa 的话数据库相关工作量基本可以忽略. 这些工作我认为 JPA 比 mybatis 省事很多. 一些行业特定的项目, 几十个表, 几十个字段的, 还是得 mybatis,
lonelymarried
2021-02-10 23:12:41 +08:00
确实难用,还不如用 mybatis,写 raw sql 方便
XiLemon
2021-02-10 23:45:15 +08:00
@iamppz #28 您说的交给原生 SQL 处理指的是什么方式呢,用 @Query 注解吗,确实没有银弹,但是有相对的比较嘛

@wc951 #29 确实缺乏这方面的理解

@idoggy #30 能说的具体一点么 -_-||

@hantsy #32 确实不熟悉 JPA,记得刚开始学习 Java 这一套时,主流框架还是 SSH,然后转变成 SSM 了。Hibernate 这个词最早还是在 Win10 休眠启动的时候学会的这个词儿~~~,学习过 MyBatis 的部分源码,Hibernate 未曾了解过。

@Cbdy #34 -_-|| 大佬制定规则,打工人照着搬砖。。。

@onikage #35 主要 MyBatis 更自由吧

@lonelymarried #36 0.0... 确实习惯了 MyBatis 这一套
mmdsun
2021-02-11 00:28:52 +08:00
spring data jpa 也能用外部 xml 文件写 SQL 不是非得用注解,参考 XML named query 。
update 指定条件,jpa 一般都是先 select 出来再 set 值更新的。
如果你在用 ORM 框架写 SQL 的话,那本身出发点就错了。尝试用"对象导航"方式获取数据,jpa 是可以配置一对多关系的。
如果你的业务是超过 3 张表关联又需要各种组合条件查询那还是 mybatis 适合,另外反思架构的设计是否合理。
passerbytiny
2021-02-11 00:32:42 +08:00
虽然 JPA/Hibernate 从来并且也不计划抛弃 NativeSQL,但是你要不会完全脱离 NativeSQL 的纯 OOP 编程,还是死了用 JPA 的心吧。

简单来说,SQL 与 JPA 互斥。
mikulch
2021-02-11 07:07:15 +08:00
@hantsy 这两本书是不是都挺老了呀

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

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

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

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

© 2021 V2EX