Foxnic-SQL (1) —— 简介
概述
Foxnic-SQL 是基于Spring JDBC 开发的 SQL 语句执行与数据处理框架。她扩展与简化了 Spring JDBC 的功能,解决开发痛点,使基于数据库的开发更加高效简洁。
项目地址:https://gitee.com/LeeFJ/foxnic
关于 Foxnic-SQL 解决的痛点与设计初衷,可以跟进 Foxnic-SQL 的相关视频。
视频地址:http://foxnicweb.com/docs/doc.html#0,4
Foxnic-SQL 即支持以实体模型为中心的开发模式,也支持以SQL语句为中心(DBA视角)的开发模式。
Foxnic-SQL 在技术和代码层面简化开发过程,目的是使开发人员由技术聚焦转到业务聚焦和数据聚焦,专注业务落地,体现系统价值。
功能特点
Foxnic-SQL 将 SQL 语句对象化,简化 SQL 语句拼接,可调式、可输出。在语句执行上,向 JDBC 提供绑定变量的语句,向开发人员提供变量代入后的语句。所以她向 JDBC 是友好的,面对开发人员也是友好的。
SQL拼接示例-1 打开代码文件
Insert insert = new Insert("bpm_demo_leave");
insert.set("id", id)
.set("type", "type-1")
.set("begin_time", new Date())
.set("end_time", new Date())
.set("reason", "天气不错,出去旅游");
System.out.println(insert.getSQL());
//输出 : INSERT INTO bpm_demo_leave ( id , type , begin_time , end_time , reason ) VALUES ( '001' , 'type-1' , str_to_date('2022-12-01 10:13:35','%Y-%m-%d %H:%i:%s') , str_to_date('2022-12-01 10:13:35','%Y-%m-%d %H:%i:%s') , '天气不错,出去旅游' )
SQL拼接示例-2 打开代码文件
public class WhereDemo {
public Where makeWhere(String name,Integer height) {
Where where = new Where("valid = ?" ,1);
where.andLike("name",name);
where.andIf("height > ?",height);
return where;
}
public static void main(String[] args) {
WhereDemo demo=new WhereDemo();
Where wh1=demo.makeWhere("leefj",18);
System.out.println(wh1);
//输出 : WHERE valid = 1 AND name like '%leefj%' AND height > 18
Where wh2=demo.makeWhere("leefj",null);
System.out.println(wh2);
//输出 : WHERE valid = 1 AND name like '%leefj%'
Where wh3=demo.makeWhere(null,18);
System.out.println(wh3);
//输出 : WHERE valid = 1 AND height > 18
}
}
SQL输出示例(断点查看) 打开代码文件
SQL输出示例(SQL执行详情)
同时,Foxnic-SQL 支持外部的SQL文件和SQL模板,轻松复用SQL语句。外置SQL语句可以对不同类型的数据库实现适配。
外部文件示例 打开代码文件
// 在外部文件中定义语句
[query-root-orgs]
select m.*,(select count(1) from hrm_organization cm where m.id=cm.parent_id and cm.deleted=0) child_count,(select count(1) from hrm_position cm where m.id=cm.org_id and cm.deleted=0) position_count from hrm_organization m
where m.parent_id='0' and company_id=? and tenant_id=? and m.deleted=0 order by type asc, sort asc
private RcdSet queryChildOrgs(String parentId,String targetType) {
RcdSet nodes=null;
String tenantId= SessionUser.getCurrent().getActivatedTenantId();
String companyId=SessionUser.getCurrent().getActivatedCompanyId();
if(parentId==null || parentId.equals(IOrganizationService.ROOT_ID)) {
// 使用外部文件已经定义的 ID 执行语句
nodes=dao.query("#query-root-orgs",companyId,tenantId);
} else {
nodes=dao.query("#query-orgs-by-parent-id",companyId,tenantId,parentId);
}
return nodes;
}
数据库适配示例 打开代码文件
// 默认数据库执行的语句
[update-org-hierarchy-step2]
UPDATE hrm_organization c, hrm_organization p
SET c.hierarchy=CONCAT(p.hierarchy,'/',c.id)
WHERE c.tenant_id=? and p.id=c.parent_id and c.hierarchy is null and p.hierarchy is not null
// 在达梦数据库时执行该语句
[update-org-hierarchy-step2:dm]
UPDATE hrm_organization c SET
c.hierarchy=CONCAT((select p.hierarchy from hrm_organization p WHERE p.id=c.parent_id and p.hierarchy is not null),'/',c.id)
where c.hierarchy is null
Foxnic-SQL 从 DAO 出发,扩展出数据库元数据、序列生成、增删改查、SQL构建、数据集、实体、全局关系与Join等方面的特性。
元数据示例 打开代码文件
public static void main(String[] args) {
// 创建DAO
DAO dao=DBInstance.DEFAULT.dao();
// 获得所有表名
String[] tableNames=dao.getTableNames();
// 遍历表名
for (String tableName : tableNames) {
System.out.println(tableName);
}
// 获得指定表的元数据
DBTableMeta tm=dao.getTableMeta("sys_user");
// 遍历列
for (DBColumnMeta column : tm.getColumns()) {
System.out.println(column.getColumn()+"\t"+column.getLabel());
}
}
序列示例 打开代码文件
public static void main(String[] args) {
// 创建DAO
DAO dao=DBInstance.DEFAULT.dao();
String name="my-sample-demo";
DBSequence sequence=dao.getSequence(name);
// 如果不存在就创建
if(!sequence.exists()) {
// 创建序列
sequence.create(SequenceType.AI,10,4);
}
// 循环取数
for (int i = 0; i < 100; i++) {
System.out.println(i+" = "+sequence.nextLong());
}
}
数据集示例 打开代码文件
public static void main(String[] args) {
// 创建DAO
DAO dao = DBInstance.DEFAULT.dao();
RcdSet rs = dao.queryPage("select * from sys_dict where code like ?", 50, 1, "%o%");
for (Rcd r : rs) {
System.out.println(r.toJSONObject());
}
}
实体代码生成示例 打开代码文件
/**
* 实体类生成器
* */
public class EntityGenerator {
private static final String BASE_PACKAGE = "com.leefj.foxnic.sql.demo";
private DAO dao = null;
/**
* 需要首先运行 ExampleDBMetaGenerator 生成 ExampleTables 类
* */
public static void main(String[] args) {
EntityGenerator generator = new EntityGenerator();
generator.generate(ExampleTables.EXAMPLE_GOODS.$TABLE);
generator.generate(ExampleTables.EXAMPLE_ORDER.$TABLE);
generator.generate(ExampleTables.EXAMPLE_ORDER_ITEM.$TABLE);
generator.generate(ExampleTables.EXAMPLE_ADDRESS.$TABLE);
}
public EntityGenerator() {
dao = DBInstance.DEFAULT.dao();
}
public void generate(DBTable table) {
String pkg = table.name().split("_")[0];
String prefix = pkg + "_";
ModuleContext context = new ModuleContext(GeneratorUtil.initGlobalSettings(),table,prefix,BASE_PACKAGE + "." + pkg);
context.setDomainProject(GeneratorUtil.getProject());
context.setDAO(dao);
context.buildPo();
}
}
实体CRUD示例 打开代码文件
public static void demo1() {
DAO dao = DBInstance.DEFAULT.dao();
// 创建实体对象,并设置属性值
Goods goods = new Goods();
String id = IDGenerator.getSnowflakeIdString();
goods.setId(id)
.setName("大红枣")
.setPrice(new BigDecimal(2.5));
// 插入数据
dao.insertEntity(goods);
// 查询数据
goods = dao.queryEntityById(Goods.class,id);
// 修改后保存
goods.setPrice(new BigDecimal(2.6));
dao.updateEntity(goods, SaveMode.DIRTY_FIELDS);
// 再次查询
goods = dao.queryEntityById(Goods.class, id);
System.out.println(JSON.toJSON(goods));
}
关系与Join示例 打开代码文件
public static void demo_relation() {
DAO dao = DBInstance.DEFAULT.dao();
// 创建订单
Order order=new Order();
String orderId=IDGenerator.getSnowflakeIdString();
order.setId(orderId);
order.setOrderNo(IDGenerator.getNanoId(8));
order.setAmount(new BigDecimal(800));
// 创建订单的收件地址
Address address=new Address();
address.setId(IDGenerator.getSnowflakeIdString());
address.setRegionType("国内");
address.setRegionLocation("华东");
address.setAddress("宁波");
address.setName("LeeFJ");
address.setPhoneNumber("13444025142");
// 指定订单的地址ID
order.setAddressId(address.getId());
// 保存地址和订单
dao.insertEntity(address);
dao.insertEntity(order);
// 从数据库查询订单
Order orderFromDB=dao.queryEntityById(Order.class,orderId);
// 使用 join 方法关联并填充地址对象
dao.join(orderFromDB, OrderMeta.ADDRESS);
// 打印输出的数据
System.out.println(JSON.toJSON(orderFromDB));
System.out.println(JSON.toJSON(orderFromDB.getAddress()));
}
Foxnic-SQL 支持 Pojo 实体,也可以将 Pojo 类继承 Foxnic-SQL 的 Entity 类以获得更强大的功能 。以上示例中的实体数据操作、关系的Join特性就是一个很好的佐证。
Foxnic-SQL 目前已经支持的数据库类型有 Oracle、MS SQL Server,MySQL、PG、DB2、达梦、OceanBase。
接下来,让我们一起感受一下 Foxnic-SQL 带来的开发之旅吧。
应用场景
Foxnic-Web
Foxnic-Web 是一套直接面向业务模块开发的应用框架。在 Foxnic-Web 已经包含了常规应用所需的基础模块,在已有基础模块的支持下,开发者可以直接开始业务模块的开发。 Foxnic-Web 在 Spring Boot 体系上扩展,开发者容易理解与快速上手。
项目地址:https://gitee.com/LeeFJ/foxnic-web
Foxnic-EAM
实现企业对资产的基本管理,包含对资产的登记、维修、调拨、转移等基本功能的支持,并提供对资产的耗材、库存进行管理,有完善的组织架构,非常适合中小企业的需求
EAM系统整体覆盖了基本的资产管理、合同管理、运维服务、运维服务、数据中心设备管理等多个模块。
项目地址:https://gitee.com/lank/eam
Foxnic-Samples
该项目用于展示和提供 Foxnic 相关的示例工程和模版代码,本文中提供的示例代码均可在 Foxnic-Samples 中找到。