sqltoy-orm是比hibernate+myBatis更加贴合项目的orm框架,具有hibernate增删改的便捷性同时也具有比myBatis更加灵活优雅的自定义sql查询功能。 支持以下数据库:
select *
from sqltoy_device_order_info t
where #[t.ORDER_ID=:orderId]
#[and t.ORGAN_ID in (:authedOrganIds)]
#[and t.STAFF_ID in (:staffIds)]
#[and t.TRANS_DATE>=:beginDate]
#[and t.TRANS_DATE<:endDate]
mybatis的写法(一板一眼很工程化)
select *
from sqltoy_device_order_info t
<where>
<if test="orderId!=null">
and t.ORDER_ID=#{orderId}
<if test="authedOrganIds!=null">
and t.ORGAN_ID in
<foreach collection="authedOrganIds" item="order_id" separator="," open="(" close=")">
#{order_id}
</foreach>
<if test="staffIds!=null">
and t.STAFF_ID in
<foreach collection="staffIds" item="staff_id" separator="," open="(" close=")">
#{staff_id}
</foreach>
<if test="beginDate!=null">
and t.TRANS_DATE>=#{beginDate}
<if test="endDate!=null">
and t.TRANS_DATE<#{endDate}
</where>
1.2 天然防止sql注入,执行过程:
假设sql语句如下
from sqltoy_device_order_info t
where #[t.ORGAN_ID in (:authedOrganIds)]
#[and t.TRANS_DATE>=:beginDate]
#[and t.TRANS_DATE<
:endDate
]
java调用过程
sqlToyLazyDao
.
findBySql(sql,
new
String
[] {
"
authedOrganIds
"
,
"
beginDate
"
,
"
endDate
"
},
new
Object
[] { authedOrganIdAry,beginDate,
null
},
DeviceOrderInfoVO
.
class);
最终执行的sql是这样的:
1、快速分页:@fast() 实现先取单页数据然后再关联查询,极大提升速度。
2、分页优化器:page-optimize 让分页查询由两次变成1.3~1.5次(用缓存实现相同查询条件的总记录数量在一定周期内无需重复查询)
3、sqltoy的分页取总记录的过程不是简单的select count(1) from (原始sql);而是智能判断是否变成:select count(1) from 'from后语句', 并自动剔除最外层的order by
4、在极特殊情况下sqltoy分页考虑是最优化的,如:with t1 as (),t2 as @fast(select * from table1) select * from xxx 这种复杂查询的分页的处理,sqltoy的count查询会是:with t1 as () select count(1) from table1, 如果是:with t1 as @fast(select * from table1) select * from t1 ,count sql 就是:select count(1) from table1
1.3.1 分页sql示例
<!--
快速分页和分页优化演示
-->
<
sql
id
=
"
sqltoy_fastPage
"
>
<!--
分页优化器,通过缓存实现查询条件一致的情况下在一定时间周期内缓存总记录数量,从而无需每次查询总记录数量
-->
<!--
alive-max:最大存放多少个不同查询条件的总记录量; alive-seconds:查询条件记录量存活时长(比如120秒,超过阀值则重新查询)
-->
<
page-optimize
parallel=
"true"
alive-max
=
"
100
"
alive-seconds
=
"
120
"
/>
<
value
>
<![CDATA[
select t1.*,t2.ORGAN_NAME
-- @fast() 实现先分页取10条(具体数量由pageSize确定),然后再关联
from @fast(select t.*
from sqltoy_staff_info t
where t.STATUS=1
#[and t.STAFF_NAME like :staffName]
order by t.ENTRY_DATE desc
left join sqltoy_organ_info t2 on t1.organ_id=t2.ORGAN_ID
</
value
>
<!--
这里为极特殊情况下提供了自定义count-sql来实现极致性能优化
-->
<!--
<count-sql></count-sql>
-->
</
sql
>
1.3.3 分页java代码调用
* 基于对象传参数模式
public
void
findPageByEntity() {
Page
pageModel
=
new
Page
();
StaffInfoVO
staffVO
=
new
StaffInfoVO
();
//
作为查询条件传参数
staffVO
.
setStaffName(
"
陈
"
);
//
使用了分页优化器
//
第一次调用:执行count 和 取记录两次查询
Page
result
=
sqlToyLazyDao
.
findPageBySql(pageModel,
"
sqltoy_fastPage
"
, staffVO);
System
.
err
.
println(
JSON
.
toJSONString(result));
//
第二次调用:过滤条件一致,则不会再次执行count查询
//
设置为第二页
pageModel
.
setPageNo(
2
);
result
=
sqlToyLazyDao
.
findPageBySql(pageModel,
"
sqltoy_fastPage
"
, staffVO);
System
.
err
.
println(
JSON
.
toJSONString(result));
* 基于参数数组传参数
public
void
findPageByParams() {
Page
result
=
sqlToyLazyDao
.
findPageBySql(
new
Page
(),
"
sqltoy_fastPage
"
,MapKit.keys("
staffName
").values(
"
陈
"
),
StaffInfoVO
.
class);
System
.
err
.
println(
JSON
.
toJSONString(result));
1.4 最巧妙的缓存应用,将多表关联查询尽量变成单表(看下面的sql,如果不用缓存翻译需要关联多少张表?sql要有多长?多难以维护?)
1、 通过缓存翻译: 将代码转化为名称,避免关联查询,极大简化sql并提升查询效率
2、 通过缓存名称模糊匹配: 获取精准的编码作为条件,避免关联like 模糊查询
cache-type:一般针对数据字典,提供一个分类条件过滤
columns:sql中的查询字段名称,可以逗号分隔对多个字段进行翻译
cache-indexs:缓存数据名称对应的列,不填则默认为第二列(从0开始,1则表示第二列),
例如缓存的数据结构是:key、name、fullName,则第三列表示全称
<
translate
cache
=
"
dictKeyNameCache
"
cache-type
=
"
DEVICE_TYPE
"
columns
=
"
deviceTypeName
"
cache-indexs
=
"
1
"
/>
<!--
员工名称翻译,如果同一个缓存则可以同时对几个字段进行翻译
-->
<
translate
cache
=
"
staffIdNameCache
"
columns
=
"
staffName,createName
"
/>
<
filters
>
<!--
反向利用缓存通过名称匹配出id用于精确查询
-->
<
cache-arg
cache-name
=
"
staffIdNameCache
"
param
=
"
staffName
"
alias-name
=
"
staffIds
"
/>
</
filters
>
<
value
>
<![CDATA[
select ORDER_ID,
DEVICE_TYPE,
DEVICE_TYPE deviceTypeName,-- 设备分类名称
STAFF_ID,
STAFF_ID staffName, -- 员工姓名
ORGAN_ID,
CREATE_BY,
CREATE_BY createName -- 创建人名称
from sqltoy_device_order_info t
where #[t.ORDER_ID=:orderId]
#[and t.STAFF_ID in (:staffIds)]
</
value
>
</
sql
>
最跨数据库
1、提供类似hibernate性质的对象操作,自动生成相应数据库的方言。
2、提供了最常用的:分页、取top、取随机记录等查询,避免了各自不同数据库不同的写法。
3、提供了树形结构表的标准钻取查询方式,代替以往的递归查询,一种方式适配所有数据库。
4、sqltoy提供了大量基于算法的辅助实现,最大程度上用算法代替了以往的sql,实现了跨数据库
5、sqltoy提供了函数替换功能,比如可以让oracle的语句在mysql或sqlserver上执行(sql加载时将函数替换成了mysql的函数),最大程度上实现了代码的产品化。 default:SubStr\Trim\Instr\Concat\Nvl 函数;可以参见org.sagacity.sqltoy.plugins.function.Nvl 代码实现
<!--
跨数据库函数自动替换(非必须项),适用于跨数据库软件产品,如mysql开发,oracle部署
-->
<
property
name
=
"
functionConverts
"
value
=
"
default
"
>
<!--
也可以这样自行根据需要进行定义和扩展
<property name="functionConverts">
<value>org.sagacity.sqltoy.plugins.function.Nvl</value>
<value>org.sagacity.sqltoy.plugins.function.SubStr</value>
<value>org.sagacity.sqltoy.plugins.function.Now</value>
<value>org.sagacity.sqltoy.plugins.function.Length</value>
</list>
</property>
-->
</
bean
>
1.5 提供行列转换(数据旋转),避免写复杂的sql或存储过程,用算法来化解对sql的高要求,同时实现数据库无关(不管是mysql还是sqlserver)
<!--
列转行测试
-->
<
sql
id
=
"
sys_unpvoitSearch
"
>
<
value
>
<![CDATA[
SELECT TRANS_DATE,
sum(TOTAL_AMOUNT) TOTAL_AMOUNT,
sum(PERSON_AMOUNT) PERSON_AMOUNT,
sum(COMPANY_AMOUNT) COMPANY_AMOUNT
FROM sys_unpivot_data
group by TRANS_DATE
</
value
>
<!--
将指定的列变成行(这里3列变成了3行)
-->
<
unpivot
columns
=
"
TOTAL_AMOUNT:总金额,PERSON_AMOUNT:个人金额,COMPANY_AMOUNT:企业金额
"
values-as-column=
"
TRANS_AMOUNT
"
labels-as-column
=
"
AMOUNT_TYPE
"
/>
</
sql
>
<!--
行转列测试
-->
<
sql
id
=
"
sys_pvoitSearch
"
>
<
value
>
<![CDATA[
select t.TRANS_DATE,t.TRANS_CHANNEL,TRANS_CODE,sum(t.TRANS_AMT) TRANS_AMT from sys_summary_case t
group by t.TRANS_DATE,t.TRANS_CHANNEL,TRANS_CODE
order by t.TRANS_DATE,t.TRANS_CHANNEL,TRANS_CODE
</
value
>
<
pivot
category-columns
=
"
TRANS_CHANNEL,TRANS_CODE
"
start-column
=
"
TRANS_AMT
"
default-value=
"
0
"
default-type
=
"
decimal
"
end-column
=
"
TRANS_AMT
"
group-columns=
"
TRANS_DATE
"
/>
</
sql
>
1.6 提供分组汇总求平均算法(用算法代替sql避免跨数据库语法不一致)
<!--
汇总计算 (场景是sql先汇总,页面上还需要对已有汇总再汇总的情况,如果用sql实现在跨数据库的时候就存在问题)
-->
<
sql
id
=
"
sys_summarySearch
"
>
<!--
数据源sharding,多库将请求压力分摊到多个数据库节点上,支撑更多并发请求
-->
<
sharding-datasource
strategy
=
"
multiDataSource
"
/>
<
value
>
<![CDATA[
select t.TRANS_CHANNEL,t.TRANS_CODE,sum( t.TRANS_AMT )
from sys_summary_case t
group by t.TRANS_CHANNEL,t.TRANS_CODE
</
value
>
<!--
reverse 表示将汇总信息在上面显示(如第1行是汇总值,第2、3、4行为明细,反之,1、2、3行未明细,第4行为汇总)
-->
<
summary
columns
=
"
2
"
reverse
=
"
true
"
sum-site
=
"
left
"
radix-size
=
"
2
"
>
<
global
sum-label
=
"
总计
"
label-column
=
"
0
"
/>
<!--
可以无限层级的分组下去
-->
<
group
sum-label
=
"
小计/平均
"
label-column
=
"
0
"
group-column
=
"
0
"
average-label
=
"
平均
"
/>
</
summary
>
</
sql
>
1.7 分库分表
1.7.1 查询分库分表(分库和分表策略可以同时使用)
sql参见showcase项目:com/sagframe/sqltoy/showcase/sqltoy-showcase.sql.xml 文件
sharding策略配置参见:src/main/resources/spring/spring-sqltoy-sharding.xml 配置
<!--
演示分库
-->
<
sql
id
=
"
sqltoy_db_sharding_case
"
>
<
sharding-datasource
strategy=
"
hashBalanceDBSharding
"
params
=
"
userId
"
/>
<
value
>
<![CDATA[
select * from sqltoy_user_log t
-- userId 作为分库关键字段属于必备条件
where t.user_id=:userId
#[and t.log_date>=:beginDate]
#[and t.log_date<=:endDate]
</
value
>
</
sql
>
<!--
演示分表
-->
<
sql
id
=
"
sqltoy_15d_table_sharding_case
"
>
<
sharding-table
tables
=
"
sqltoy_trans_info_15d
"
strategy=
"
historyTableStrategy
"
params
=
"
beginDate
"
/>
<
value
>
<![CDATA[
select * from sqltoy_trans_info_15d t
where t.trans_date>=:beginDate
#[and t.trans_date<=:endDate]
</
value
>
</
sql
>
1.7.2 操作分库分表(vo对象由quickvo工具自动根据数据库生成,且自定义的注解不会被覆盖)
@Sharding 在对象上通过注解来实现分库分表的策略配置
参见:com.sagframe.sqltoy.showcase.ShardingCaseServiceTest 进行演示
package
com.sagframe.sqltoy.showcase.vo
;
import
java.time.LocalDate
;
import
java.time.LocalDateTime
;
import
org.sagacity.sqltoy.config.annotation.Sharding
;
import
org.sagacity.sqltoy.config.annotation.SqlToyEntity
;
import
org.sagacity.sqltoy.config.annotation.Strategy
;
import
com.sagframe.sqltoy.showcase.vo.base.AbstractUserLogVO
;
*
@project
sqltoy-showcase
*
@author
zhongxuchen
*
@version
1.0.0 Table: sqltoy_user_log,Remark:用户日志表
* db则是分库策略配置,table 则是分表策略配置,可以同时配置也可以独立配置
* 策略name要跟spring中的bean定义name一致,fields表示要以对象的哪几个字段值作为判断依据,可以一个或多个字段
* maxConcurrents:可选配置,表示最大并行数 maxWaitSeconds:可选配置,表示最大等待秒数
@Sharding
(
db
=
@Strategy
(
name
=
"
hashBalanceDBSharding
"
,
fields
=
{
"
userId
"
}),
//
table = @Strategy(name = "hashBalanceSharding", fields = {"userId" }),
maxConcurrents
=
10
,
maxWaitSeconds
=
1800
)
@SqlToyEntity
public
class
UserLogVO
extends
AbstractUserLogVO
{
private
static
final
long
serialVersionUID
=
1296922598783858512L
;
/*
* default constructor
*/
public
UserLogVO
() {
super
();
开源地址: github: https://github.com/sagframe/sagacity-sqltoy gitee: https://gitee.com/sagacity/sagacity-sqltoy idea 插件 (可直接在 idea 中检索安装): https://github.com/threefish/sqltoy-idea-plugins 更新内容 1、全面开放xml中的功能在findByQuery中:QueryExecutor().summary().colsChainRatio().rowsChainRatio()等 即:开放汇总、行与行环比、列与列环比,完善filters中的cacheArg、exclusive、defaultValue、...
开源地址: github: https://github.com/sagframe/sagacity-sqltoy gitee: https://gitee.com/sagacity/sagacity-sqltoy idea 插件 (可直接在 idea 中检索安装): https://github.com/threefish/sqltoy-idea-plugins 更新内容 1、sql查询filters中增加默认值设置 2、修复@ loop在循环内容以:loopValues[i]参数开头且没有空格场景下的缺陷 3、针对(h2\kingbase\postgresql15\dm\sqlite\gaussdb) 强化saveOrUpdate\saveAllIgnoreE...
开源地址: github: https://github.com/sagframe/sagacity-sqltoy gitee: https://gitee.com/sagacity/sagacity-sqltoy idea 插件 (可直接在 idea 中检索安装): https://github.com/threefish/sqltoy-idea-plugins 更新内容 1、针对数据库数组类型,POJO被映射成List场景(正常Array数组类型)的支持 2、修复对GaussDB sequence批量保存场景的问题修复 sqltoy 的关键优势:
//------------------了解 sqltoy的关键优势: -----...
sqltoy-orm 5.2.51 已经发布,ORM 框架 此版本更新内容包括: 1、新增LightDao更加简洁的API(不影响之前SqlToyLazyDao),修复5.2.50 版本findTop中一个参数类型定义缺陷 2、优化updateByQuery中set(表字段名)跟公共属性基于POJO属性名赋值不一致的缺陷
<dependency>
<groupId>com.sagframe</groupId>
<artifactId>sagacity-sqltoy</artifactId>
<version>5.2.51</version>
</dependency>
<dependency>
<groupId>com....
开源地址: github: https://github.com/sagframe/sagacity-sqltoy gitee: https://gitee.com/sagacity/sagacity-sqltoy idea 插件 (可直接在 idea 中检索安装): https://github.com/threefish/sqltoy-idea-plugins sqltoy-lambda https://gitee.com/gzghde/sqltoy-plus 基于sqltoy的后台脚手架系统 https://gitee.com/momoljw/sss-rbac-admin 更新内容 1、统一字段处理IUnifyFieldsHandler中增加了对createTime、updateTime等时...
开源地址: github: https://github.com/sagframe/sagacity-sqltoy gitee: https://gitee.com/sagacity/sagacity-sqltoy idea 插件 (可直接在 idea 中检索安装): https://github.com/threefish/sqltoy-idea-plugins 更新内容 1、修复cacheMatchKeys(CacheMatchFilter cacheMatchFilter, String[] matchRegexes)优先相等匹配未生效问题 2、convertType支持多级对象转换、改成了工具类形式不再依赖SqlToyContext,可以直接用Mappe...
开源地址: github: https://github.com/sagframe/sagacity-sqltoy gitee: https://gitee.com/sagacity/sagacity-sqltoy idea 插件 (可直接在 idea 中检索安装): https://github.com/threefish/sqltoy-idea-plugins 更新内容 1、修复sqlserver数据库update和saveOrUpdate decimal类型精度丢失问题 感谢: 彭工的反馈,sqlserver数据库用户请及时更新 sqltoy 的关键优势:
//------------------了解 sqltoy的关键优势: -------...
开源地址: github: https://github.com/sagframe/sagacity-sqltoy gitee: https://gitee.com/sagacity/sagacity-sqltoy idea 插件 (可直接在 idea 中检索安装): https://github.com/threefish/sqltoy-idea-plugins 更新内容 1、针对一个sql查询将结果封装成主子对象结构,实际join到的子对象数据为空的过滤,在注解中增加了notNullField 属性
* 主键关联子表信息,增加了notNullField 标记子表结果不为null的判断依据字...
开源地址: github: https://github.com/sagframe/sagacity-sqltoy gitee: https://gitee.com/sagacity/sagacity-sqltoy idea 插件 (可直接在 idea 中检索安装): https://github.com/threefish/sqltoy-idea-plugins 更新内容 1、强化接口参数合法性校验 2、修复unifyFieldsHandler未配置场景下产生的NullPointException 3、完善SqlInterceptor,为开发者提供特定场景下进行执行干预提供条件 4、优化sql语句中查询条件参数值为n...
开源地址: github: https://github.com/sagframe/sagacity-sqltoy gitee: https://gitee.com/sagacity/sagacity-sqltoy idea 插件 (可直接在 idea 中检索安装): https://github.com/threefish/sqltoy-idea-plugins 更新内容 1、优化sql中存在问号字符的校验,改为只针对分页场景下传参模式是?号做校验 2、针对多数据源,提供@Primary的数据源获取 sqltoy 的关键优势:
//------------------了解 sqltoy的关键优势: -------...
开源地址: github: https://github.com/sagframe/sagacity-sqltoy gitee: https://gitee.com/sagacity/sagacity-sqltoy idea 插件 (可直接在 idea 中检索安装): https://github.com/threefish/sqltoy-idea-plugins 更新内容 1、优化反向缓存匹配获取精准key值用in(:keys) 代替 like :nameKeyWords场景
<sql id="qstart_order_search">
<filters>
unmatched-return-self:缓存未匹配到key直接用名称代替(默认t...
开源地址: github: https://github.com/sagframe/sagacity-sqltoy gitee: https://gitee.com/sagacity/sagacity-sqltoy idea 插件 (可直接在 idea 中检索安装): https://github.com/threefish/sqltoy-idea-plugins 更新内容 1、优化并行分页,使用统一的线程池减少线程池的创建和销毁 2、DataSourceUtils增加initialize方法,强化线程安全 3、优化部分代码提升效率 感谢 rabbit 进行深度压力测试,编写并行分页的优化 sqltoy 的...
开源地址: github: https://github.com/sagframe/sagacity-sqltoy gitee: https://gitee.com/sagacity/sagacity-sqltoy idea 插件 (可直接在 idea 中检索安装): https://github.com/threefish/sqltoy-idea-plugins 更新内容 1、优化雪花算法主键策略单例初始化定义,增加init初始化方法,避免线程安全 感谢网友:rabbit的反馈 sqltoy 的关键优势:
//------------------了解 sqltoy的关键优势: ---------------------------...
开源地址: github: https://github.com/sagframe/sagacity-sqltoy gitee: https://gitee.com/sagacity/sagacity-sqltoy idea 插件 (可直接在 idea 中检索安装): https://github.com/threefish/sqltoy-idea-plugins 更新内容 1、修复@value(:name) 存在$\符号,导致正则表达式替换bug 2、增强cacheMatchKeys支持数组,将多个名称通过like匹配找到精准的key
String[] cacheMatchKeys(CacheMatchFilter cacheMatchFilter, Stri...
开源地址: github: https://github.com/sagframe/sagacity-sqltoy gitee: https://gitee.com/sagacity/sagacity-sqltoy idea 插件 (可直接在 idea 中检索安装): https://github.com/threefish/sqltoy-idea-plugins 更新内容 1、改进对mysql新驱动cte场景的兼容,with tmp as (),tmp2() 别名不能跟逗号、括号连在一起(连在一起mysql新驱动报错) 2、改进分页查询,采用并行模式时共用单个connection导致资源竞争,改成分别获取c...
开源地址: github: https://github.com/sagframe/sagacity-sqltoy gitee: https://gitee.com/sagacity/sagacity-sqltoy idea 插件 (可直接在 idea 中检索安装): https://github.com/threefish/sqltoy-idea-plugins 更新内容 1、发版sqltoy5.3.0 适配springboot3.x sqltoy 的关键优势:
//------------------了解 sqltoy的关键优势: -------------------------------------------------------------------------------------...
开源地址: github: https://github.com/sagframe/sagacity-sqltoy gitee: https://gitee.com/sagacity/sagacity-sqltoy idea 插件 (可直接在 idea 中检索安装): https://github.com/threefish/sqltoy-idea-plugins 更新内容 1、tree-sort功能增加sum-columns,支持树结构逐层汇总
<sql id="tree_sort">
<tree-sort id-column="organ_id" pid-column="organ_pid" sum-columns="staff_cnt"/>
<value>
<![CDATA[
selec...
开源地址: github: https://github.com/sagframe/sagacity-sqltoy gitee: https://gitee.com/sagacity/sagacity-sqltoy idea 插件 (可直接在 idea 中检索安装): https://github.com/threefish/sqltoy-idea-plugins 更新内容 1、优化多租户的支持,findByEntity之前遗漏了多租户的支持 2、兼容postgresql ilike 场景 3、loadByIds兼容loadByIds(entityClass,idList)场景 4、提供spring.sqltoy.executeSqlBlankToNull参数,设置更...
开源地址: github: https://github.com/sagframe/sagacity-sqltoy gitee: https://gitee.com/sagacity/sagacity-sqltoy idea 插件 (可直接在 idea 中检索安装): https://github.com/threefish/sqltoy-idea-plugins 更新内容 1、增强错误提示,优化部分代码 2、增加tree-sort对树结构数据排序
<sql id="qstart_treeTable_search">
<value>
<![CDATA[
select * from sqltoy_organ_info t order by OR...
开源地址: github: https://github.com/sagframe/sagacity-sqltoy gitee: https://gitee.com/sagacity/sagacity-sqltoy idea 插件 (可直接在 idea 中检索安装): https://github.com/threefish/sqltoy-idea-plugins 更新内容 1、优化了BeanUtil.convertType 采用更加精准高效的int匹配 2、优化了MapperUtils支持多级父类匹配 3、修复oracle、db2 等数据库saveOrUpdate公共属性字段赋值,日期类型不支持的缺陷 4、其它部分细节优...