ObjectiveSQL 稳定版本发布 1.4.0

2020-11-30 11:15:39 +08:00
 Braisdom

你可能喜欢他,也有可能讨厌他,就像 Lombok 这种 Java 编程模式一样,也会被很多人拒绝。只不过这次你遇到的不再是处理简单的 setter 和 getter,而是用这种编程风格来解决 ORM 的简单查询和复杂 SQL 编程。

经过这段时间各位提交的 Bug 和版本的基本特性,发 1.4.0 稳定版本,主要特性如下:

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

完整特性如下:

1 简单查询(首先需要定义一个以 DomainModel Annotation 定义的模型)

@DomainModel
public class Member {
    private String no;
    @Queryable
    private String name;
    private Integer gender;
    private String mobile;
    private String otherInfo;

    @Relation(relationType = RelationType.HAS_MANY)
    private List<Order> orders;
}

1.1 数据持久化

Member.create(newMember);
Member.create(newMember, true); // Create a member without validating
Member.create(Member.newInstanceFrom(memberHash));
Member.create(new Member[]{newMember1, newMember2, newMember3}, false);

Member.update(1L, newMember, true); // Update a member with primary key
Member.update("name = 'Smith => Jackson'", "name = 'Alice'");

Member.destroy(1L); // Delete a member with primary key
Member.destroy("name = 'Mary'");

// Execute SQL
Member.execute(String.format("DELETE FROM %s WHERE name = 'Mary'", Member.TABLE_NAME));

1.2 事务处理

@Transactional
public static void makeOrder(Order order, OrderLine... orderLines) throws SQLException {
  Order.create(order, false);
  OrderLine.create(orderLines, false);
}

1.3 查询与统计

Member.countAll();
Member.count("id > ?", 1);
Member.queryByPrimaryKey(1);
Member.queryFirst("id = ?", 1);
Member.query("id > ?", 1);
Member.queryAll();

1.4 分页查询

Page page = Page.create(0, 10);// Create a Page instance with current page and page size
PagedList<Member> members = Member.pagedQueryAll(page, Member.HAS_MANY_ORDERS);

1.5 关联对象查询

// Querying objects with convenient methods, and it will carry the related objects
Member.queryAll(Member.HAS_MANY_ORDERS);
Member.queryByPrimary(1, Member.HAS_MANY_ORDERS);
Member.queryByName("demo", Member.HAS_MANY_ORDERS);

2 复杂 SQL 查询

Java 代码:

// SQL programming with Java syntax without losing the features of SQL syntax
Order.Table orderTable = Order.asTable();
Select select = new Select();

select.project(sum(orderTable.amount) / sum(orderTable.quantity) * 100)
        .from(orderTable)
        .where(orderTable.quantity > 30 &&
            orderTable.salesAt.between($("2020-10-10 00:00:00"), $("2020-10-30 23:59:59")))
        .groupBy(orderTable.productId);

生成的 SQL 代码:

-- SQL syntax is the same as Java syntax
SELECT ((((SUM(`T0`.`amount` ) / SUM(`T0`.`quantity` ) )) * 100))
FROM `orders` AS `T0`
WHERE ((`T0`.`quantity` > 30) AND 
       `T0`.`sales_at` BETWEEN '2020-10-10 00:00:00' AND '2020-10-30 23:59:59')
GROUP BY `T0`.`product_id`
3329 次点击
所在节点    程序员
43 条回复
PopRain
2020-11-30 11:32:31 +08:00
生成的 SQL 最好是参数化查询,这样效率高且可以避免 SQL 注入
Braisdom
2020-11-30 11:35:00 +08:00
是的,SQL 注入是 ObjectiveSQL 下一阶段的重点特性
GM
2020-11-30 11:58:58 +08:00
删除使用 destroy 挺反直觉的,毕竟 sql 里删除就是 delete,大部分人平时用的也都是 delete,建议使用 delete
替换 destroy 。
beginor
2020-11-30 12:25:35 +08:00
@GM 我也是, 在 destroy 那里愣了一下才明白过来。
beginor
2020-11-30 12:28:35 +08:00
持续关注楼主的这个项目, 昨天试用了了一下,确实挺不错的。 不过和 c# 的 linq 比起来, 还是差那么点意思, 主要还是受限于 java 的语法。
Braisdom
2020-11-30 12:41:27 +08:00
@GM
@beginor
两位,先陈述一下我的设计思路,问题域分两块:SQL 域和 Java 所解决的业务域,在业务域中存在的是对象行为,创建(create),更新(update),和销毁 /删除(destroy),而 SQL 中通常是 Insert, update, delete 。

我的设计来自于 Rails 的设计,本质上怎么用问题都不大,只是习惯问题而已
Braisdom
2020-11-30 12:42:48 +08:00
@beginor 感谢支持,下一阶段 ObjectiveSQL 项目的主要工作是:数据迁移(Migration) 和 SQL 注入(SQL Injection)
chinvo
2020-11-30 12:47:41 +08:00
虽然不写 Java,但是还是点个赞

顺道安利一波 .net

建议对 .net 还挺留在 framework 2.0 时代认知的人了解一下新时代的 .net (core 、5.0 、6.0):开放、高效、易用
Braisdom
2020-11-30 12:48:50 +08:00
@chinvo .NET 的发展过程值得学习
chinvo
2020-11-30 12:51:33 +08:00
@Braisdom #9 没拥抱开源之前的 .net 也不能说不好,但是真的用不起,Windows Server 授权、Visual Studio 授权、SQL Server 授权……

拥抱开源之后和 RHEL 合作,在 RH 系上是商业级的支持力度

不过在我看来 .Net 最强的地方还是 LinQ 和 EF,写业务逻辑最优选择
Braisdom
2020-11-30 12:54:48 +08:00
@chinvo 我之前没有接触过.NET 的 entity framework,也是最近才看到,

我设计 ObjectiveSQL 的主要目的是为了解决复杂 SQL 的处理,现有的框架维护动态 SQL 太痛苦,时间一长,项目根本无法维护。

简单 SQL 现有的框架已经做的很不错了,只是顺带把它做了而已
chinvo
2020-11-30 12:59:10 +08:00
@Braisdom #11 其实我比较好奇,很多语言都有类似 EF/LinQ 的 Orm,Java 生态圈竟然没有么 😂

我有了解过 Java 的几种 Orm,有一些是 xml 描述( Java 生态圈好像挺依赖 xml 的),有一些甚至还要写“类 SQL”,给我的直观感受就是难用、反人类
GM
2020-11-30 13:03:23 +08:00
@chinvo 推荐个应用框架? ABP 太复杂了,感觉不适合技术能力一般的团队用。
GM
2020-11-30 13:05:27 +08:00
@chinvo
真的没有。
受制于语言表达能力,很多很好用的功能 Java 里就是无法用正常 Java 代码写出来,只能用代码生成器、动态字节码等别扭的方式来实现。
Braisdom
2020-11-30 13:05:36 +08:00
@chinvo 我也有同感,我之前写了很多年的 Java,中途写 Ruby 和 Python,也是最近两年才又写 Java,ORM 又是一个系统无法避免的问题,用起来太痛苦,所以才会写 ObjectiveSQL 这个项目的。

Java LINQ 也有,但很不好用,只能处理一些相对简单的查询,join 子查询,union,复杂表达式等(多层 case when 或者窗口函数等),这些处理起来很不舒服
chinvo
2020-11-30 13:08:46 +08:00
@GM #13 个人、小团队,直接裸的 Asp.Net MVC 啊。
GM
2020-11-30 13:16:31 +08:00
@chinvo ASP.NET MVC 这个只能做个单体应用,想做个分布式的需要自己手撸各种基础设施功能。
renyijiu
2020-11-30 13:19:17 +08:00
有个不太相关的问题,是否支持 grpc protobuf ?
chinvo
2020-11-30 13:21:32 +08:00
@GM #17 分布式(Actor 模型)用 Orleans,多租户用 MapEndpoint,UoW 其实用不着,因为 EF 本身就是 UoW 模型
Braisdom
2020-11-30 13:24:01 +08:00
@renyijiu protobuf 只是一个协议封装,用在数据传输的,现在比较流行,相比很早的 TLV 灵活很多。rpc 只是远程调用,现在微服务里比较流行

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

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

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

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

© 2021 V2EX