在开发者的圈子里,没当说到一种技术好或者不好,都会引发激烈或者不激烈的争论,直到一个开发者出来说 PHP 是世界上最好的语言,大家伙儿才会纷纷退去继续写代码。

今天说 JPA 的问题不是想引发什么讨论或者骂战,单纯的就是我不喜欢 JPA 。没错,就是这么 Real。

说到 Java 开发,涉及到数据库访问的,主要就两种框架,一个是 MyBatis ,另一个就是 JPA。据说是国外 JPA 用的比较多,国内 MyBatis
用的比较多。国内为什么 MyBatis 用的多呢,传说是因为整个阿里系都用它。

JPA 全称是Java 持久化 API ,它的目的就是帮助我们提高开发效率,它的核心是 Java持久化查询语言
(JPQL),对存储在关系数据库中的实体进行查询。在语法上类似于SQL查询,但是操作的是实体对象而不是直接对数据库表进行操作。(摘自 wiki)

使用 JPA 开发的流程如下:
1、将数据库表映射到项目实体中
2、生成对应的 Repository
3、实现 Service ,Service 中调用 Repository
JPA 帮你省事儿的地方就在 Repository
里,对于那些比较简单的逻辑,比如单表查询,直接根据名字就可以实现查询逻辑。对于大部分查询来说,真的很省事儿。但刚开始用的时候,确实感觉有些莫名其妙。

确实如此,如果你用过 JPA ,有些时候它确实对开发效率有很大提升,JPA 想要做的就是尽量让你少写 sql,甚至不写 sql。基于这种思想,JPA
实现了它自己的一套语法、注解规则。

JPA
要用各种注解配合来实现数据实体间的一对多、多对多等等的关联关系。正因为这样,我觉得实体变得不单纯是实体,而是掺杂的逻辑在里面,也增加了实体的复杂度,对于比较复杂的业务来说,很容易造成实体间直接或间接的循环引用。

你如果想用 JPA,除了要掌握各种注解外,对于稍微复杂的查询,还要掌握它的那套写法,比如下面这种代码:
Specification<CmContent> specification = (root, criteriaQuery,
criteriaBuilder) -> { Predicate p =
criteriaBuilder.equal(root.get("deleted").as(Boolean.class), false); Predicate
news = criteriaBuilder.equal(root.get("cntntType"),
ContentType.CNTNTTP_NEWS.name()); Predicate salon =
criteriaBuilder.equal(root.get("cntntType"), ContentType.CNTNTTP_SALON.name());
Predicate type = criteriaBuilder.or(news, salon); ...
而且你想要实现一个 join 查询也是够费劲的,除了要写上面那套代码外,还要在实体上做手脚,想到就想哭,有没有。难道直接写个 sql
不好吗,为什么要这么糟蹋自己。

还有一点,JPA
有些注解用上了之后会影响到数据库层面,比方说关键外键的注解,如果你用默认设置,这个外键就真的会应用到数据库表里,在表上建外键。还有其他的一些 ORM
框架也是如此,这是我完全不能接受的,凭什么,凭什么在我的数据库上改东西。

愿我参与的项目中没有 JPA。公司有个项目用到了 JPA ,我也参与了一部分,写的代码不算多,除了令我头疼之外,没有体会到 JPA
的半点好处,这其中当然很可能是由于我的水平有限,或者说我写的 JPA 代码不够多,或者我根本没有领会到 JPA
的精髓所在。总之不管怎么样,对不起,愿我不会再碰到 JPA。

当然这么说肯定是有失偏颇,有些同学可能会对此嗤之以鼻。没错,有同事就是这样说的:事物存在即合理,JPA 这么多年了,如果不好用怎么会还有这么多人用,而且国外
JPA 使用者众多,难道人家都有问题。

如果只是简单的项目,业务一点也不复杂,不复杂到连个 join 都没有的项目,可以用 JPA ,其他的情况下,真的不用它最好。用 JPA
的感觉就像是被绑上了手脚,失去了自由。不自由,毋宁死。纵使千般好,少了自由,我就拒绝它。而 MyBatis 恰恰就是给开发者自由的一个框架。

还是那句话,不自由,毋宁死。这是第一个,恐怕也是最后一个用 JPA 的项目了。

不要吝惜你的「推荐」呦

欢迎关注,不定期更新本系列和其他文章
古时的风筝 ,进入公众号可以加入交流群