Java 都这么多年过去了,生产级别数据库操作库除了 JPA 和 Mybatis 还有什么? JPA 和 mybatis-plus 比优势在什么地方?

2021-07-31 09:33:58 +08:00
 pigbug
8979 次点击
所在节点    Java
70 条回复
Leviathann
2021-07-31 09:37:50 +08:00
太多了
jooq
jdbi
querydsl

kotlin 可以使用所有 java 生态然后还有官方的 exposed
sagaxu
2021-07-31 09:37:57 +08:00
试试 jooq
br00k
2021-07-31 09:40:33 +08:00
我挺喜欢 querydsl,SQL 、MongoDB 都可以支持。
Cbdy
2021-07-31 09:45:34 +08:00
Cbdy
2021-07-31 09:48:38 +08:00
当然是 JDBCTemplate 啦,再精妙的 ORM,都不如直接写 SQL 清晰利落
Leviathann
2021-07-31 09:51:43 +08:00
@Cbdy 根据查询条件拼接 sql,要修改重构的话这种纯字符串的方案巨恶心
jones
2021-07-31 10:02:38 +08:00
jdbctemplate, 其他都是浮云, 代码就应该是代码的样子, jpa 会陷入 Annotation 地狱, mybatis 会陷入 XML 地狱
Cbdy
2021-07-31 10:05:56 +08:00
@Leviathann 不同的方案有不同的写法、劣势、优势,直接写字符串明了,虽然动态性差,但是在要动态性的场景可以通过多拆几个方法,或者换动态的 SQL Builder 解决

你这是要求一个完美的方法解决所有问题吗?很可惜软件开发没有银弹
chendy
2021-07-31 10:11:10 +08:00
jdbctemplate 遇到条件不定的 sql 就很头大了
alamaya
2021-07-31 10:14:47 +08:00
居然有吹直接写 sql 的,这是返祖现象吗?
notejava
2021-07-31 10:14:54 +08:00
习惯了使用 mybatis-plus,兼顾了单表操作和手写 sql 。
limbo0
2021-07-31 10:21:35 +08:00
mybatis-plus + 1 尽量不手写 sql, 维护太麻烦
bitmin
2021-07-31 10:48:01 +08:00
jdbctemplate 动态 sql 我的解决方案是先写完整 sql,自己写一个工具类检查入参空参数并删除 sql 中相应的语句。

在 idea 中 sql 都有代码提示,也可以格式化显示,代码中用多行字符串展示看起来很清晰。
abcbuzhiming
2021-07-31 10:48:16 +08:00
这本质是两种思想的碰撞,JPA 的思维是 ORM,mybatis 则来自“sqlUtils”(sql 帮助工具)。

在关系数据库群雄争霸的那个时代,SQL 标准没有统一,在编程界的当时有一个迫切的需求:如果我半途要换关系数据库怎么办?不像现在这个 MySQL“称霸世界”(并没有)的时代,当时做到一半换数据库是真的常见的需求。而当时 SQL 作为一种 4GL 语言其实思想并没有广泛的被人接受,当时的业界还是面向对象的天下。于是就有人说:为什么不能用面向对象来映射关系数据库的表呢?这就是 ORM(Object Relational Mapping,对象关系映射)最初的思想来源。也是最主要的两个 ORM 库,Hibernate 和.Net Entity Framework 的指导思想。

时间飞速前进,新世纪后发生了两个非常主要的变化:

第 1 个变化是,关系数据库面对海量的互联网数据开始变的力不从心,为了解决海量数据的问题(当时大数据还没有像现在这么发达),不得不妥协,把单库拆分成多库,这么一拆之后,关系数据库之前以强约束,关联关系计算为卖点的特性,不再是优势(拆分之后的库无法使用这些特性,只能搞什么最终一致,Base 理论之类的聊以自慰),这也是为啥 MySQL 这种在经典关系数据库理论看上去简直就是个残废的关系数据库大行其道的原因。同时,因为经典关系数据库的特性不再重要,关系数据库开始沦为数据仓库,选哪家的数据库就变的不再重要了,更换数据库变成了伪需求,不再存在,ORM 理论的重要来源:屏蔽各个关系数据库之间的不同点,以让用户更换数据库无忧,这一最初的重要需求,不再存在。


第 2 个变化是,进入新世纪后,SQL 作为一个 4GL 语言的价值终于被发现,大家纷纷表示这种“do not tell me how to do,tell me what you want(不要告诉我怎么干,告诉我你要什么)”的模式真是太香了;而且一众 NoSQL 的鼓吹者们高举大旗准备驱逐关系数据库,结果闹了很久后发现自己拿 SQL 居然毫无办法,只能捏着鼻子,纷纷又开始在自己的查询器上加上了 SQL 支持。传统关系数据库是没落了,但是 SQL 以及背后承载的关系运算的思维,在新时代反而是大行其道。复杂查询直接上 SQL 那感觉是真香,连新普的大数据从业者都自嘲自己说:后端是 CRUD Boy,我们就是 SQL Boy 。


总之,新世纪的竞争里,目前看是 SQL 赢了,ORM 的思维只比较适合无连表的 CRUD,对单表或多个单表执行 OLTP 业务,此时的 ORM 是比你写多个 insert,select 啥的方便的,但是一旦涉及到复杂的联表,group,having 查询,大家否纷纷直接上 SQL 更方便。

另外从业界的进化你也可以看得出来,纯正的 ORM,在 Hibernate 和.Net Entity Framework 之后几乎就没有再看到出名的了,JPA 则是从 Hibernate 发展来的,可以看做延续和强化,但本质不会变。但是各种"SQL 工具类"型的查询库,还在层出不穷的出,而且这些工具并非墨守成规,Ruby on Rails 开历史先河,吸收 ORM 对单表查询很友好这个优势,发展出了 Active Record 这种即可以从单表结构直接映射出对象,并可以在查询的时候以链式调用的方式注入查询条件;同时,都保留了能够方便自定义 SQL 的能力。其它 Sql 工具一看纷纷跟进,包括现在 Mybatis 的几个强化工具都是这个思路。

所以我觉得接下来一段比较长的时间,除非出现新的变革,占优势的应该还是各种更亲和 Sql,但是同时具备表映射对象能力的各种 SQL 帮助工具。
echo1937
2021-07-31 10:48:33 +08:00
Spring Data 是 Spring 提供的一个操作数据的框架,旨在统一和简化对各类型持久化存储,
而 Spring Data JPA 只是 Spring Data 框架下的一个基于 JPA 标准操作数据的模块。
它的优势是 RDBMS 、Redis 、MongoDB 、ES 、Cassandra 、Solr 、GemFire 等等都可以用同一套的 API 去访问,这点是 mybatis-plus 做不到的。
缺点是国内用的少(国外 99%都是这个),有一定学习门槛,注解比较多,没有 JDK text block 的话,写原生查询 SQL 看着不美观。

如果你业务离不开 mybaits,mybatis-plus 确实非常好用。
yema50
2021-07-31 10:54:29 +08:00
@limbo0 最近也在尝试用 mybatis-plus, 请问一般查数据的时候,假如有一两个条件参数, 你们一般是在 Mapper 里定义好方法然后 service 里直接调用, 还是直接在 service 里构造 QueryWrapper 查询呢
abcbuzhiming
2021-07-31 10:58:13 +08:00
@yema50 单表查询请一律不要自己定义 mapper 和 service,直接用表反向映射生成实体,mapper,service,然后你构建 QueryWrapper 注入查询条件,用 mapper 还是用 service 就随你了。

这类工具的设计目的就是为了解决纯 SQL 工具在单表查询时不如 ORM 方便的。如果你单表查询还要去自己定义 mapper 和 service,那等于这个工具没有起作用
yema50
2021-07-31 11:23:15 +08:00
@abcbuzhiming 感谢回复,可能我没有表述清楚, 我举个例子。现在有个 User 实体,对应的 UserMapper, UserService,现在有个需求要根据 username 查询,我想到的实现方式有 1. UserMapper 里定义一个方法 findUserByName(@Param("name") String name), 然后上面加上对应的注解和 SQL,再在 userService 里直接调用; 2. 在 userService 里需要查询的地方构造 QueryWrapper<User> query....., query.eq("name", "name"), 然后再查询。

我的困惑是:1. 如果使用第二种方式,可能会有多处需要用到类似查询的地方, 那就是代码里会有多处构造相同 QueryWrapper 的代码; 2.如果使用第一种方式, 可能有时查询条件会增减,比如某处需要再加上 age 作为条件,这样又感觉不够动态

请大家指教
AlkTTT
2021-07-31 11:25:46 +08:00
@alamaya 号是 14 年的,年龄不小了。难以接受新的技术,最后终究会被淘汰,可能几年后我们也会这样
Kipp
2021-07-31 11:30:49 +08:00
@yema50 #18 之前也思考过这个问题,觉得还是放在 mapper 里比较好,不然 QueryWrapper 到处飞,之前的 QueryWrapper 也没法复用

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

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

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

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

© 2021 V2EX