朋友开发的开源项目,喜欢的话去https://github.com/braisdom/ObjectiveSql 点个star
项目介绍ObjectiveSQL 是一个Java ORM 框架,以ActiveRecord 模式基础,结合JSR 269 API 实现数据库访问Java 代码的动态生成,从而提高生产效率,主要特性包括:
- 动态生成数据模型访问数据库的 JAVA API 代码,其中包括数据库访问的SELECT、INSERT、UPDATE 和DELETE
- 根据Relation 注解的定义,在查询时自动填充关联对象,同时也避免N+1 查询问题
- 提供多种方式构造数据模型,主要以Java Bean PropertyDescriptor 形式,也支持Map 形式绑定属性
- 多数据源支持,只需在DomainModel 中指定数据模型所属的数据源
- 事务支持,只需要在模型方法中指定Transaction 注解,系统自动生成数据为事务代码
- 灵活扩展,系统针对业务领域中可能遇见的扩展点提供Interface 和注入接口,主要包括:JDBC 执行器、数据类型转换、SQL 查询、SQL 持久化等
- 面向对象SQL(开发中,预计在1.4.0 版本发布)
- ObjectiveSQL 集成了Apache Dbutils 实现基础ORM 特性,包括:SQL 的执行、数据模型与Table Row 之间的相互转换、以及基础的JDBC 特性。Apache Dbutils 只提供了能用的ORM 特性,缺少关联关系,并且与应用系统之间的结合相对不够友好,本质上是一个高度抽象、且灵活的技术框架。
- Transition 层,也是一般ORM 框架中必备的一个特性,主要用于数据模型与数据库之间的数据转换,它有两个扩展方法:rising 用于将数据库的数据转换为Java 类型的数据,sinking 用于将Java 类型的数据转换为数据库类型的数据,由于不同数据库类型也可能出现不一样的转换方法,DateTime 是很多数据库的转换方式都不一样,所以Transition 也是高度被扩展的接口,Transition 会作为一个扩展点注入Apache Dbutils。
- API 层,是以面向对象的方式封装高度抽象的数据库访问API,主要为DomainModel 生成的具体API 服务,应用系统也可以结合 Query 和Persistence 两个接口封装出符合业务特性的API。
- DomainModel 是对业务系统逻辑的抽象和封装,而业务逻辑中会涉及大量数据库的读写,在ObjectiveSQL 框架下,不再需要显式的编写相应的数据读写逻辑,只关注真实的业务逻辑即可。
本文档主要介绍:如何通过ObjectiveSQL 结合 SpringBoot 实现MySQL 数据库的增、删、改和查,以及关联关系的查询。通过示例,你可以看出ObjectiveSQL 如何通过极少的编码,就可以实现数据库访问。项目完整代码请参考:SpringBootExample。
1 ObjectiveSQL 依赖安装(Maven & Gradle)
<dependencies>
<dependency>
<groupId>com.github.braisdom</groupId>
<artifactId>objective-sql</artifactId>
<version>1.3.6</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>8</source>
<target>8</target>
<encoding>UTF-8</encoding>
<compilerArgs>
<arg>-Xplugin:Manifold</arg>
</compilerArgs>
<annotationProcessorPaths>
<path>
<groupId>systems.manifold</groupId>
<artifactId>manifold-ext</artifactId>
<version>2020.1.27</version>
</path>
<path>
<groupId>com.github.braisdom</groupId>
<artifactId>objective-sql</artifactId>
<version>1.3.6</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
compile group: 'com.github.braisdom', name: 'objective-sql', version: '1.3.6'
点击“Maven 仓库”可以找到最新版本和其它的依赖方式配置,目前最新版本为: 1.3.6
2 IntelliJ 插件安装
- MAC 操作系统
- Preferences >> Plugins >> Marketplace >> 搜索 “ObjectiveSql” >> 安装
- Windows 操作系统
- File >> Settings >> Plugins >> Marketplace >> 搜索 “ObjectiveSql“>> 安装
3 Annotation Processor 设置
Settings/Preferences >> Annotation Processor >> 选择项目后,勾选 “Enable annotation processing”
4 数据库脚本
CREATE DATABASE IF NOT EXISTS `objective_sql` CHARACTER SET utf8 COLLATE utf8_general_ci;
CREATE TABLE IF NOT EXISTS `objective_sql`.`members`(
`id` INT UNSIGNED AUTO_INCREMENT,
`no` VARCHAR(100),
`name` VARCHAR(100),
`gender` INT(2),
`mobile` VARCHAR(11),
`other_info` VARCHAR(512),
`registered_at` DATETIME,
`updated_at` DATETIME,
PRIMARY KEY ( `id` )
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
5 定义领域模型
@DomainModel
public class Member {
private String no;
private String name;
private Integer gender;
private String mobile;
}
所谓领域模型,基实就是Java 中是一个定义基础数据结构的 Class,而在数据库领域是一张表的结构定义(也称为Schema),一行数据对应Class 的一个实例。以面向对象设计理论的基础去理解,对数据库表的查询、更新、修改和删除应当以静态行为的形式体现在该模型中。
6 使用实践
结合SpringBoot 我们提供了一份完整的使用示例,覆盖了常用场景,完整代码请参考:MembersController.java
6.1 创建会员
"/members")(
public ResponseObject create( RequestObject rawMember) throws SQLException {
Member dirtyMember = Member.newInstanceFrom(rawMember, false);
Member member = Member.create(dirtyMember, true);
return ResponseObject.createSuccessResponse(member);
}
6.2 根据会员号查询单个会员
// Querying a member by member no
@GetMapping("/members/{no}")
public ResponseObject getMember(@PathVariable("no") String memberNo) throws SQLException {
Member member = Member.queryByNo(memberNo);
return ResponseObject.createSuccessResponse(member);
}
6.3 查询所有会员
// Querying all members
@GetMapping("/members")
public ResponseObject getMembers() throws SQLException {
List<Member> members = Member.queryAll();
return ResponseObject.createSuccessResponse(members);
}
6.4 根据会员号更新会员
// Updating a member with member no
@PutMapping("/members/{no}")
public ResponseObject updateMember(@PathVariable("no") String memberNo,
@RequestBody RequestObject rawMember) throws SQLException {
Member member = Member.queryByNo(memberNo);
Member.update(member.getId(), Member.newInstanceFrom(rawMember), true);
return ResponseObject.createSuccessResponse();
}
6.5 根据会员号删除会员
// Deleting a member with member no
@DeleteMapping("/members/{no}")
public ResponseObject deleteMember(@PathVariable("no") String memberNo) throws SQLException {
int deleteCount = Member.destroy("member_no = ?", memberNo);
return ResponseObject.createSuccessResponse(deleteCount);
}
7 小结
通过上述示例,应用系统可以以极简单代码,实现对数据库的存储和查询,从而将设计和编码的重心转移到应用系统本身,ObjectiveSql 提供了丰富的API和扩展接口,最大限度的满足应用系统的实际需求,当前只展示示例仅仅是冰山一角,详细内容请看后续。
IntelliJ IDEA 插件安装由于数据库访问Java API 是由ObjectiveSQL 在编译期间生成,在IntelliJ IDEA 在编码过程中无法识别生成的方法或属性,ObjectiveSQL 提供了IntelliJ IDEA 插件,用于解决编码过程中的编译错误和动态代码提示。
1 应用市场安装
进入IntelliJ IDEA 的 Preference 对话框后,以“ObjectiveSQL” 关键字进行搜索,并点击安装
2 本地安装最新版本
由于IntelliJ IDEA 插件仓库审核需要一定时间,针对一些Bug 的紧急修复会临时发布最新版本供用户下载,可以按下列方式,从本地安装ObjectiveSQL 插件。
名称映射规则下载完成后,进行Preference -> Plugins 选项中点击 Install Plugin From Disk… 菜单,选中下载的 .zip 文件,即可完成安装
Class 名称与Table 名称、字段名称与Column 名称的缺省映射规则是一个开发团队成熟的重要标志,团队成员遵循统一的规则降低了沟通成本,并且也减少了开发过程中出错的机率,与敏捷开发中的隐喻也是有着异曲同工的作用。
Java 的开发体系中一直强调“扩展性”,认为技术型框架中存在的强制遵循的规则,阻碍了系统的可扩展性,却不知,固化一些已经约定俗成的规则,是系统开发中效率的关键,就像人类社会发展了数千年,除了法律的约束外,更多的是民间存在的习俗,有了这些被人所认可的习俗,人与人之间才能够形成有效的生产力。
规则会迭代和变化,这并不意味着规则不重要,很多人会挑战规则的内容和形成过程,但挑战的结果就是:又形成了一套新的规则。
1 类与字段命名规则
缺省情况下,类名遵循Java 的规范,以驼峰的单数形式命名,而表名则以下划线 “” 分隔单词的复数形式命名,Java 字段以驼峰形式命名,而数据库表Column名称以下划线“” 分隔单词,具体示例如下:
Java 类名 | 数据库表名 |
| |
| |
| |
| |
| |
Java 字段名称 | 数据库 Column 名称 |
| |
| |
2 关联对象名称约束
ObjectiveSQL 定义的关联关系主要包括三种:HAS_ONE,HAS_MANY,和BELONGS_TO,其中HAS_MANY 为复杂形式,其它均为单数形式,其它命名规则如下:
- HAS_MANY 时,主表中用于承载关联对象的字段以驼峰形式的复数命名
- HAS_ONE 时,主表中用于承载关联对象的字段以驼峰形式的单数命名
- BELONGS_TO 时,从表中用于承载关联对象的字段以驼峰形式的单数命名
- 其它用于映射数据库字段的命名规则遵循普通字段命名规则