分析一下 Java ORM 框架的原理,大家怎么看?

2020-12-15 12:45:59 +08:00
 Braisdom

Java 的 ORM 框架发展了很多年,一直存在各种各样的问题,相信大家的体会比我还要深,到底这是什么什么呢?我从两个角度来分析一下,大家看看对不对?

1 )语义表达的双重性

一个 Java Bean 的定义,只能表达一种语义,就是与其它相关的 Java 类相互协作实现一项特性,通常用于数据的载体,但不能表达数据库交互时的 SQL 的语义,两种内存的语义差异很大(例如:Java Field 在数据库中映射为 Column,一个 Column 可以进行排序、算术运算、比较运算等),很难通过 Annotation 进行描述,除非 Java 中增加新的特性,用于描述一个 Java Class 的多重语义。既然一个 Java Class 无法满足双重语义的描述,只能新增代码进行定义和描述,此时又出现重复代码和变更的一致性,通过 Maven 或 APT 形式生成,也会存在每次变更后,都需要重新运行任务,才能正常使用,使的开发过程变得更糟。

2 )语法一致性

Java 语法与 SQL 语法从语义上说基本是一致的,但表现形式不一样,例如:Java 中逻辑表达式:a && b 或者 a || b,而 SQL 中则是 a AND b 或者 a OR c,两种类型表达语义上一致,但语法上不能直接互换。同时,也无法 Java 对语义的解析和执行过程进行干预,也就导致了 Java 的表达式无法直接转换为 SQL 表达式,只能以字符串的形式进行拼接,通过对字符串拼接过程进行抽象和封装,形成一系列 API,这也就导致了简单的表达式变成若干 Java 方法的嵌套,严重影响了代码的可理解性。

ObjectiveSQL 完美的解决了上述两个问题,通过 Java 代码的动态生成和 Java 运算符重载等特性,有兴趣的同学可以发起挑战: https://github.com/braisdom/ObjectiveSql

4628 次点击
所在节点    Java
34 条回复
wysnylc
2020-12-15 16:44:58 +08:00
@neochen13 #3 看的烦
lidlesseye11
2020-12-15 19:54:26 +08:00
@brezp
真心求问,不点进来怎么知道是推广?是有啥能直接显示帖子内容的客户端 /插件吗?
guyeu
2020-12-15 21:49:06 +08:00
确实有点为赋新辞强说愁的感觉;

楼主为了解决关系型数据库的模型、语义等和 Java 的对象模型不一致的问题,发明了一堆注解和一个 DSL ;
其他人为了解决同样的问题,发明了一个概念叫对象关系映射,同样的,发明了一堆注解和一个 DSL ( Criteria );

so,大家都是一样的东西,你这个咋就“完美的解决了上述两个问题”呢。。。
Braisdom
2020-12-15 21:55:48 +08:00
@guyeu 立场不同,说法就不同,经历不同,也会有不同的说法。我只是朴素的阐述自己的理论,ORM 的出现已经 20 多年了,DSL 的理解有很多层,不同人有不同的理解。
另外说一句,我很不喜欢发明新说法,Java 领域有太多新概念了,“语义表达的双重性” 是我的理解,当然也有其它的说明法,我只是表达一个 Java Field 需要表达两种不同的语义。语法的一致性是一个事实,是我用 Java 的运算符重载解决的特性,大家可以有不同的理解。

欢迎挑战,最近在推广,我很希望听到不同的意见,感谢各位。
cloudhuang
2020-12-15 22:15:55 +08:00
@Braisdom 这里的 “ SQL 域” 是指什么?是标准 SQL 吗?我不是太理解您说的这种方式。如果是标准 SQL,那么 order 这种方式是通过字句的方式来解决的,其本质其实也是编程语言。
拿您的例子来说,name 存储为状态这个本身是没有问题的,难道排序后的 name 就不是 name 了?

回到本质的问题,如果同数据库的交互还是 SQL,那么规避不了拼接 SQL 这个本质,只是的形式不同而已(但形式上确实会有优劣之分,不过会有些主观)。您的这个 ObjectiveSQL 我没有去看,或者采用了其他方式,您可以说明一下,可能 ObjectiveSQL 操作数据库,不是最终在数据库层面去执行 SQL 的,而是通过其他方式。


> 2) 至于 Java 的运算符重载,你可以参考: https://www.v2ex.com/t/734572#reply103
里面有详细的描述和讨论。
cloudhuang
2020-12-15 22:20:18 +08:00
> 2) 至于 Java 的运算符重载,你可以参考: 里面有详细的描述和讨论。

嗯,这个就没啥可说的了,您说这个是运算符重载就是运算符重载吧。但我认为这个是通过函数调用来模拟运算符操作,而运算符(比如+,-,==)重载本质上应该是一种多态。
Braisdom
2020-12-15 22:27:16 +08:00
@cloudhuang
1 )本质上 ObjectiveSQL 还是 SQL 的拼接,就像所有的应用层网络协议一下,底层还是 TCP/IP,目前我还不能超越 SQL,但我有更深层次的想法,目前还不成熟。

2 ) SQL 域指的就是传统 SQL 编程,Java Class 中的 name 就有两层含义,一层是表示传统 Java Bean,只能承载 String 类型的值,另一层,就是需要承载作为 SQL 语句抽象后的 Column 含义,它的行为和状态是 String 不具备的,例如:

User.Table user = User.asTable();
Select select = new Select();

select.project(count())
.from(user)
.groupBy(user.name.).orderBy(user.name.asc());

这里的 user.name 其实是 Column 的实例。
levon
2020-12-15 23:41:59 +08:00
@Braisdom 做 entity framework 的 java 版本,绝对红遍半边天
bsg1992
2020-12-16 09:12:51 +08:00
去看看 EF 吧 EF 算是目前实现最好的了
cloudhuang
2020-12-16 09:14:38 +08:00
> 这里的 user.name 其实是 Column 的实例。
用你的话来解释,那么"user.name",应该是属于 Column 的语义,也不是"name"的语义了,只是恰好你的 column 的名字也叫"name"这个名字。
Braisdom
2020-12-16 09:48:14 +08:00
@levon 您是 V 站的老人,感谢您的鼓励,我会继续努力,不能只停留在到处推广,而是真正的做好项目。
brezp
2020-12-16 10:31:03 +08:00
@lidlesseye11 楼主的头像很有特点
Braisdom
2020-12-16 11:08:52 +08:00
@brezp 是本人的漫画版本
Rorysky
2020-12-16 17:57:33 +08:00
@neochen13 付出很多的项目,可以理解

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

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

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

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

© 2021 V2EX