历经 3 年,终于得以实现了

2020-11-21 23:19:37 +08:00
 Braisdom

写了 15 年的程序,人到中年总有很多话要说,千言万语尽在项目里,里面有我想说的一切。

项目地址: https://github.com/braisdom/ObjectiveSql

ObjectiveSQL 是我构想了很长时间,到底是让 Java 像 SQL 一样编程,还是让 SQL 让 Java 一样编程,纠结了很久,还是让 Java 更像 SQL,Java 的语法表现力不够,只能扩展 Javac,实现了算法运算,比较运算,逻辑运算符重载,并封装了常用数据的的函数,抽象了 Expression,使的 Java 非常接的 SQL,同时也实现了简单 SQL 编程的代码生成,基本不需要写代码,也不需要配置就能实现简单 SQL 的编程,话不多说,先看示例,有兴趣可以到 github 上看。

Order.Table orderTable = Order.asTable();
Select select = new Select();

select.project(sum(orderTable.amount) / sum(orderTable.quantity) * 100)
    .from(orderTable)
    .groupBy(orderTable.productId);
Member.Table member = Member.asTable();
Order.Table order = Order.asTable();

Select select = new Select();

select.from(order, member)
        .where(order.memberId.eq(member.id));
select.project(member.no,
        member.name,
        member.mobile,
        countDistinct(order.no).as("order_count"),
        sum(order.quantity).as("total_quantity"),
        sum(order.amount).as("total_amount"),
        min(order.salesAt).as("first_shopping"),
        max(order.salesAt).as("last_shopping"));
select.groupBy(member.no, member.name, member.mobile);

ObjectiveSQL is an ORM framework in Java base on ActiveRecord pattern, which encourages rapid development and clean, codes with the least, and convention over configuration.

Features

25973 次点击
所在节点    Java
163 条回复
Braisdom
2020-11-22 21:48:57 +08:00
@fangcan 感谢支持
pythonee
2020-11-22 21:51:56 +08:00
点赞
有对比过 linq 吗
bugmakerxs
2020-11-22 22:01:00 +08:00
其实解决 orm 还有另一个思路是避免复杂 sql,比如微服务;如果一定要复杂 sql 才能解决的问题,我们一般都交给大数据团队做离线计算了。个人认为复杂 sql 不管怎么表达,,都挺难维护的。。
Braisdom
2020-11-22 22:11:16 +08:00
@bugmakerxs 离线计算需要一定的前提,离线计算只是输出中间结果,前台的计算复杂度依然存在。
Braisdom
2020-11-22 22:12:49 +08:00
@pythonee 你有兴趣可以看一下贴子前面的讨论,Linq 分为两种,1 )内存计算,2 ).NET Entity Framework 实现,很优秀,值得借鉴
liuhan907
2020-11-22 22:44:04 +08:00
@Braisdom 其实 ef core 最优秀,或者说最能节省精力的地方在于自动追踪查询出来的结构的数据变化并生成 update 语句。所有的操作都是强类型。不过性能上就弱一些。再次看了你的项目的 repo,你这个我觉得更加类似 dapper 。
beginor
2020-11-22 22:53:00 +08:00
不知楼主有没有兴趣了解一下这个 https://github.com/re-motion/Relinq, .Net 上的不管是 EF 还是 NHibernate, 都是用了这个来进行 linq 表达式树的转换
beginor
2020-11-22 22:54:34 +08:00
@beginor 手滑了, 正确的地址是 https://github.com/re-motion/Relinq
momocraft
2020-11-23 01:23:55 +08:00
有点像 slick
momocraft
2020-11-23 01:24:26 +08:00
纯用 java 做这个真的有毅力..
miaoever
2020-11-23 02:57:38 +08:00
我司 (也算大厂了吧) 做过类似的事情, 主要针对的场景是 OLAP 的 SQL. 我们的做法是提供两套 API ,一套是 SQL 本身,另一套是类似于楼主的这种链式调用 API (不过我们是 Python), 同时我们两套 API 可以混用 .

我们做这个工作一个重要的出发点能够对 SQL 进行静态的类型检查 (以及其他的一些语义检查). 做法上和楼主不一样的是, 我们不基于宿主语言 (Java or Python) 的类型系统,而是将 SQL 或者 链式 API 的程序统一翻译成一个中间表达形式 (IR), 然后再其上做类型检查. 此外, 我们不仅仅是对单个 SQL 做类型检查, 更重要的是对整个 OLAP 链路上所有具有数据血缘的 SQL 会做全局检查, 以保证链路上任何 SQL 的修改都都不会破坏其上游及下游 SQL 的合法性.
当然类型检查只是我们做的一方面, 我们还做了很多其他的更重要的语义检查, 在这儿就先不展开说了.


另一很重要的动机是 SQL 的的提高可组合型以及复用性. 举个简单的例子, 用楼主的给的场景来说, 对于以下的这个计算(当然我们的现实中的场景比这个复杂的多):

sum(orderTable.amount) / sum(orderTable.quantity) * 100

我们的系统里, 这个计算可以定义成一个库函数 (def sum(double)->double). 这个函数可以像普通编程语言中的库函数一样在任何一个 SQL 中进行调用:

SELECT sum(1.0) FROM table1
// SELECT.PROJECT(sum(1.0)).....

同时, 我们的静态检查工具能够静态的当前调用环境中 SUM 函数时输入类型和返回类型做类型检查.
Mithril
2020-11-23 07:25:31 +08:00
支持,Java 和.NET 都写的表示 Java 真的缺少 Linq 这种东西。
Linq to object 自动在内存中处理所有 IEnumerable,而且支持并行。
Line to SQL 会自动编译成对应的 SQL,而且无法编译的现在并不会自动在内存处理,会直接报错。虽然免不了手写 SQL,但不是整个项目所有地方都需要真正手工优化 SQL 的。
最关键的是两者语法基本一致,写起来非常流畅。
wanguorui123
2020-11-23 07:49:42 +08:00
有点像 FreeSQL
xyooyx
2020-11-23 08:22:53 +08:00
不管怎么样先嘲讽,思想就很有问题
luoyikang52066
2020-11-23 08:46:48 +08:00
支持
CallMeADU
2020-11-23 10:00:13 +08:00
出发点不错,技术能力也很强。不过从多数程序员角度肯定是不喜欢用 java 代码去实现 sql 生成的,一不直观,二代码有 sql 写的爽吗?还是喜欢各自领域各司其职
Braisdom
2020-11-23 10:12:14 +08:00
@lqw3030 我的想法是很有问题的,充满了对现实的不满,我之前写了四,五年的 Ruby, Python,回到 Java 尽然快 20 年了一直都没什么变化,十分气愤
Braisdom
2020-11-23 10:14:58 +08:00
@miaoever 通过函数实现算术表达现在比较流行,但表达式过于复杂,函数也力不从心的。

例如:
IF((COUNT(DISTINCT IF((dateDiff('second', t1.finish_time, t2.sales_at) AS t) < 14*24*60*60 AND t > 0, t2.member_no, NULL)) AS p6) IS NULL, 0, p6) AS sales_member_count

这样的表达式,如果全部是函数封装,根本没人看得懂
wysnylc
2020-11-23 10:33:13 +08:00
支持聚合函数的 JPA,但是分页子查询排序这些问题不可能维护的完的
Braisdom
2020-11-23 10:38:05 +08:00
@wysnylc 复杂性是无法避免的问题,也是客观的事实,ObjectiveSQL 的目的是让复杂性变得更清晰,更可读,而不能完全降低复杂性。

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

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

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

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

© 2021 V2EX