jSqlBox5.0.4 发布,精雕细凿,写出可维护的 SQL

jSqlBox是一个Java DAO工具,主要特点是架构优、尺寸小、功能全,基本上所有与数据库操作相关的功能,jSqlBox都已提供。它的主要特点有:  

1.只有单个1M大小的jar包,不依赖任何第三方库。它可以独立使用,也支持在Spring环境下使用。  
2.内核基于DbUtils并与之兼容,最差情况下可以降级当成DbUtils来使用,上手快。 
3.提倡在java里拼写SQL,独创参数内嵌式SQL写法(下面会详细介绍)。  
4.支持分库分表、多租户、声明式事务、分布式事务、长文本、ActiveRecord。
5.支持80多种数据库方言,分页、函数变换、DDL生成、实体源码生成、实体或数据库结构导出Excel。
6.主要的实体类注解兼容JPA标准。 

在Java里直接写SQL,独创参数内嵌式SQL写法是jSqlBox的主要特点。传统的SQL写法有什么问题? 最大的问题就是它是“不可维护”的,比如说下面这个SQL, 当要添加、更新或删除列时会很困难,因为要找到列名和参数的对应位置需要花时间,SQl越长,越难维护:

insert into tb_price_setting (id,code,adult_price,child_price,total_price,adult_note,child_note,
currency,type,time_zone,status,include_tax,adult_discount,child_discount,total_discount,
created_at,updated_at,) values(1200, "BJD837434", 50, 30, 80, "15以上全价", "8-15半价", "USD, 8,
"UTC", "A", 3.03, 0, 0, 0, "2019-09-17 04:07:55", "2020-03-10 22:43:00";

而采用jSqlBox后,写法是这样的:

DB.exe("insert into tb_price_setting (", //
	"id,", par(1200), //
	"code,", par("BJD837434"), //
	"adult_price,", par(50), //
	"child_price,", par(30), //
	"total_price,", par(80), //
	"adult_note,", par("15以上全价"), //
	"child_note,", par("8-15半价"), //
	"currency,", par("USD"), //
	"type,", par(8), //
	"time_zone,", par("UTC"), //
	"status,", par("A"), //
	"include_tax,", par(3.03), //
	"adult_discount,", par(0), //
	"child_discount,", par(0), //
	"total_discount,", par(0), //
	"created_at,", par("2019-09-17 04:07:55"), //
	"updated_at,", par("2020-03-10 22:43:00"), //
	")", valuesQuestions());

在jSqlBox中SQL的参数是可以挪动到任意位置的,在不降低SQL的可读性和保持原生SQL功能的前提下,这种写法极大地提高了SQL的可维护性,新增或删除列时只要增删对应的行即可。相比与JPA利用实体ORM进行CRUD, MyBatis利用模板书写SQL, jSqlBox这种写法是最简单明了的,直接拼写SQL,打完就收工,不需要引入额外的实体类和模板。模板的问题是需要两次书写,列名在模板里写一次,在参数代入时要又要再写一次,增加了维护工作量。

有眼尖的同学可能会发现,这种写法列名字符串直接写在SQL里,如果数据库字段变动,IDE不能发现和报错,也就是说,SQL是不支持重构的,这个问题怎么解决? 不用担心,本次更新提供了解决方案。

方案一,利用jSqlBox最新出炉的Q类生成工具,根据数据库内容自动生成所有表格的Q类,并且可以定制Q类格式。每次数据库变动,重新生成一遍Q类即可。Q类中包含了所有表格字段常量。则上述的SQL可以写成如下形式:

QTbPriceSetting p=QTbPriceSetting.instance;
DB.exe("insert into ",p," (", //
	p.id, par(1200), //
	p.code, par("BJD837434"), //
	p.adult_price, par(50), //
	p.child_price, par(30), //
	p.total_price, par(80), //
	p.adult_note, par("15以上全价"), //
	p.child_note, par("8-15半价"), //
	p.currency, par("USD"), //
	p.type, par(8), //
	p.time_zone, par("UTC"), //
	p.status, par("A"), //
	p.include_tax, par(3.03), //
	p.adult_discount, par(0), //
	p.child_discount, par(0), //
	p.total_discount, par(0), //
	p.created_at, par("2019-09-17 04:07:55"), //
	p.updated_at, par("2020-03-10 22:43:00"), //
	")", valuesQuestions());

方案二: 利用QueryDSL的Maven插件,适用于已存在JPA实体类的场合。这个插件可以扫描项目已有的JPA实体类,生成Q类,jSqlBox借花献佛可以把它的Q类拿过来用于拼接原生SQL。使用示例如下,和方案一的用法类似,在需要表格名的时候,直接传入Q类实例,在需要SQL列名的时候,传入Q类的常量字段即可:

QUser u = QUser.user;
DB.exe("insert into ", u, " (",  u.id, ",", par(1),  u.userName, ",", par("张三"),  u.userAge, par(15),  ")", valuesQuestions());

以上两种方案的详细使用介绍请参见jSqlBox用户手册的"支持重构的SQL"一节。

jSqlBox (5.0.4.jre8版) 本次更新内容:
1. 如上所述,新增生成和使用Q类来写出支持重构的SQL。根据数据库生成Q类只需要在jSqlBox中调用以下方法即可:   
      TableModelUtils.db2QClassSrcFiles(ctx.getDataSource(), ctx.getDialect(), "c:\\outputFolder", "com.demo", "Q");
2. 新增多租户功能,详见用户手册"jSqlBox进阶-主从、分库分表、多租户"一节的介绍。
3. TableModelUtilsOfDB添加了compareDB方法,这是个小功能,可以用来比较两个数据库结构是否有差异,用法如下:
   TableModelUtilsOfDb.compareDbIgnoreLength(connection1,  connection2);
4. DbContext新增一个SqlItemhandler配置选项,可以用来定制自已的Sql条目解析器。
5. DbPro类中新增qryBooleanValue方法,返回一个boolean类型值。
6. DB类中新增notBlank和noBlank两个方法,用来在动态拼接SQL时判断空字符串条件,和原有的notNull、noNull使用方法类似,比如说下面这种写法,当
用user.getAge()为null时不会插入age列,当user.getEmail()为null或空白字符串时,不会插入email列:

DB.exe("insert into users (", //
           " name ,", par("Sam"), //
            notNull("age,", user.getAge()), //
            notBlank("email,", user.getEmail()), //
            " address ", par("Canada"), //
            ") ", valuesQuestions()); 

用DB中的when()方法也可以实现根据条件来动态拼接SQL,但notBlank/noBlank/notNull/noNull这类判空方法写起来更简洁一些。 

猜你喜欢

转载自www.oschina.net/news/126460/jsqlbox-5-0-4-released