迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
开源软件名称:sagacity-sqltoy开源软件地址:https://gitee.com/sagacity/sagacity-sqltoy开源软件介绍:在线文档sqltoy-online-doc 网友海贝(hugo)提供xml中sql完整配置github地址WORD版详细文档(完整)请见:docs/睿智平台SqlToy5.1 使用手册.doc范例演示项目快速集成演示项目
快速上手项目
POJO和DTO 严格分层演示项目sharding分库分表演示dynamic-datasource多数据源范例nosql演示(mongodb和elasticsearch)sqltoy基于xml配置演示QQ 交流群:531812227最新版本号:
更新内容:
4.x 升级5.x 项目影响点
1. 前言1.1 sqltoy-orm是什么sqltoy-orm是比hibernate+myBatis(plus)更加贴合项目的orm框架(依赖spring),具有jpa式的对象CRUD的同时具有比myBatis(plus)更直观简洁性能强大的查询功能。支持以下数据库:
1.2 jdk版本要求1.8+2. 快速特点说明2.1 对象操作跟jpa类似并有针对性加强(包括级联)
StaffInfoVO staffInfo = new StaffInfoVO(); //保存 sqlToyLazyDao.save(staffInfo); //删除 sqlToyLazyDao.delete(new StaffInfoVO("S2007")); //public Long update(Serializable entity, String... forceUpdateProps); // 这里对photo 属性进行强制修改,其他为null自动会跳过 sqlToyLazyDao.update(staffInfo, "photo"); //深度修改,不管是否null全部字段修改 sqlToyLazyDao.updateDeeply(staffInfo); List<StaffInfoVO> staffList = new ArrayList<StaffInfoVO>(); StaffInfoVO staffInfo = new StaffInfoVO(); StaffInfoVO staffInfo1 = new StaffInfoVO(); staffList.add(staffInfo); staffList.add(staffInfo1); //批量保存或修改 sqlToyLazyDao.saveOrUpdateAll(staffList); //批量保存 sqlToyLazyDao.saveAll(staffList); ............... sqlToyLazyDao.loadByIds(StaffInfoVO.class,"S2007") //唯一性验证 sqlToyLazyDao.isUnique(staffInfo, "staffCode"); 2.2 支持代码中对象查询
/** * @todo 通过对象传参数,简化paramName[],paramValue[] 模式传参 * @param <T> * @param sqlOrNamedSql 可以是具体sql也可以是对应xml中的sqlId * @param entity 通过对象传参数,并按对象类型返回结果 */ public <T extends Serializable> List<T> findBySql(final String sqlOrNamedSql, final T entity);
public Page<StaffInfoVO> findStaff(Page<StaffInfoVO> pageModel, StaffInfoVO staffInfoVO) { // sql可以直接在代码中编写,复杂sql建议在xml中定义 // 单表entity查询场景下sql字段可以写成java类的属性名称 return findPageEntity(pageModel, StaffInfoVO.class, EntityQuery.create() .where("#[staffName like :staffName]#[and createTime>=:beginDate]#[and createTime<=:endDate]") .values(staffInfoVO) // 字典缓存必须要设置cacheType // 单表对象查询需设置keyColumn构成select keyColumn as column模式 .translates(new Translate("dictKeyName").setColumn("sexTypeName").setCacheType("SEX_TYPE") .setKeyColumn("sexType")) .translates(new Translate("organIdName").setColumn("organName").setKeyColumn("organId")));}
//演示代码中非直接sql模式设置条件模式进行记录修改public Long updateByQuery() { return sqlToyLazyDao.updateByQuery(StaffInfoVO.class, EntityUpdate.create().set("createBy", "S0001") .where("staffName like ?").values("张"));}//代码中非直接sql模式设置条件模式进行记录删除sqlToyLazyDao.deleteByQuery(StaffInfoVO.class, EntityQuery.create().where("status=?").values(0)); 2.3 极致朴素的sql编写方式
//1、 条件值处理跟具体sql分离//2、 将条件值前置通过filters 定义的通用方法加工规整(大多数是不需要额外处理的)<sql id="show_case"><filters> <!-- 参数statusAry只要包含-1(代表全部)则将statusAry设置为null不参与条件检索 --> <eq params="statusAry" value="-1" /></filters><value><![CDATA[ select * from sqltoy_device_order_info t where #[t.status in (:statusAry)] #[and 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] ]]></value></sql> 2.4 天然防止sql注入,执行过程:
select *from sqltoy_device_order_info t where #[t.ORGAN_ID in (:authedOrganIds)] #[and t.TRANS_DATE>=:beginDate] #[and t.TRANS_DATE<:endDate]
sqlToyLazyDao.findBySql(sql, MapKit.keys("authedOrganIds","beginDate", "endDate").values(authedOrganIdAry,beginDate,null), DeviceOrderInfoVO.class);
select *from sqltoy_device_order_info t where t.ORDER_ID=? and t.ORGAN_ID in (?,?,?) and t.TRANS_DATE>=?
2.5 最为极致的分页2.5.1 分页特点说明
2.5.2 分页sql示例<!-- 快速分页和分页优化演示 --><sql id="sqltoy_fastPage"> <!-- 分页优化器,通过缓存实现查询条件一致的情况下在一定时间周期内缓存总记录数量,从而无需每次查询总记录数量 --> <!-- parallel:是否并行查询总记录数和单页数据,当alive-max=1 时关闭缓存优化 --> <!-- 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 ) t1 left join sqltoy_organ_info t2 on t1.organ_id=t2.ORGAN_ID ]]> </value> <!-- 这里为极特殊情况下提供了自定义count-sql来实现极致性能优化 --> <!-- <count-sql></count-sql> --></sql> 2.5.3 分页java代码调用/** * 基于对象传参数模式 */public void findPageByEntity() { StaffInfoVO staffVO = new StaffInfoVO(); // 作为查询条件传参数 staffVO.setStaffName("陈"); // 使用了分页优化器 // 第一次调用:执行count 和 取记录两次查询 // 第二次调用:在特定时效范围内count将从缓存获取,只会执行取单页记录查询 Page result = sqlToyLazyDao.findPageBySql(new Page(), "sqltoy_fastPage", staffVO);} 2.6 极为巧妙的缓存翻译,将多表关联查询尽量变成单表
//支持对象属性注解模式进行缓存翻译@Translate(cacheName = "dictKeyName", cacheType = "DEVICE_TYPE", keyField = "deviceType")private String deviceTypeName;@Translate(cacheName = "staffIdName", keyField = "staffId")private String staffName; <sql id="sqltoy_order_search"> <!-- 缓存翻译设备类型 cache:具体的缓存定义的名称, cache-type:一般针对数据字典,提供一个分类条件过滤 columns:sql中的查询字段名称,可以逗号分隔对多个字段进行翻译 cache-indexs:缓存数据名称对应的列,不填则默认为第二列(从0开始,1则表示第二列), 例如缓存的数据结构是:key、name、fullName,则第三列表示全称 --> <translate cache="dictKeyName" cache-type="DEVICE_TYPE" columns="deviceTypeName" cache-indexs="1"/> <!-- 员工名称翻译,如果同一个缓存则可以同时对几个字段进行翻译 --> <translate cache="staffIdName" 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> 2.7 并行查询
// parallQuery 面向查询(不要用于事务操作过程中),sqltoy提供强大的方法,但是否恰当使用需要使用者做合理的判断/** * @TODO 并行查询并返回一维List,有几个查询List中就包含几个结果对象,paramNames和paramValues是全部sql的条件参数的合集 * @param parallQueryList * @param paramNames * @param paramValues */public <T> List<QueryResult<T>> parallQuery(List<ParallQuery> parallQueryList, String[] paramNames, Object[] paramValues);
//定义参数String[] paramNames = new String[] { "userId", "defaultRoles", "deployId", "authObjType" };Object[] paramValues = new Object[] { userId, defaultRoles, GlobalConstants.DEPLOY_ID, SagacityConstants.TempAuthObjType.GROUP };// 使用并行查询同时执行2个sql,条件参数是2个查询的合集List<QueryResult<TreeModel>> list = super.parallQuery( Arrays.asList( ParallQuery.create().sql("webframe_searchAllModuleMenus").resultType(TreeModel.class), ParallQuery.create().sql("webframe_searchAllUserReports").resultType(TreeModel.class)), paramNames, paramValues); 2.8 跨数据库支持
<!-- 跨数据库函数自动替换(非必须项),适用于跨数据库软件产品,如mysql开发,oracle部署 --> <property name="functionConverts" value="default"> <!-- 也可以这样自行根据需要进行定义和扩展 <property name="functionConverts"> <list> <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> -->
<sql id="sqltoy_showcase"> <value> <![CDATA[ select * from sqltoy_user_log t where t.user_id=:userId ]]> </value> </sql> <!-- sqlId_数据库方言(小写) --> <sql id="sqltoy_showcase_mysql"> <value> <![CDATA[ select * from sqltoy_user_log t where t.user_id=:userId ]]> </value> </sql> 2.9 提供行列转换、分组汇总、同比环比等
2.9.1 行转列(列转行也支持)<!-- 行转列 --><sql id="pivot_case"> <value> <![CDATA[ select t.fruit_name,t.order_month,t.sale_count,t.sale_quantity,t.total_amt from sqltoy_fruit_order t order by t.fruit_name ,t.order_month ]]> </value> <!-- 行转列,将order_month作为分类横向标题,从sale_count列到total_amt 三个指标旋转成行 --> <pivot start-column="sale_count" end-column="total_amt" group-columns="fruit_name" category-columns="order_month" /></sql>
2.9.2 分组汇总、求平均(可任意层级)<sql id="group_summary_case"> <value> <![CDATA[ select t.fruit_name,t.order_month,t.sale_count,t.sale_quantity,t.total_amt from sqltoy_fruit_order t order by t.fruit_name ,t.order_month ]]> </value> <!-- reverse 是否反向 --> <summary columns="sale_count,sale_quantity,total_amt" reverse="true"> <!-- 层级顺序保持从高到低 --> <global sum-label="总计" label-column="fruit_name" /> <group group-column="fruit_name" sum-label="小计" label-column="fruit_name" /> </summary></sql>
2.9.3 先行转列再环比计算<!-- 列与列环比演示 --><sql id="cols_relative_case"> <value> <![CDATA[ select t.fruit_name,t.order_month,t.sale_count,t.sale_amt,t.total_amt from sqltoy_fruit_order t order by t.fruit_name ,t.order_month ]]> </value> <!-- 数据旋转,行转列,将order_month 按列显示,每个月份下面有三个指标 --> <pivot start-column="sale_count" end-column="total_amt" group-columns="fruit_name" category-columns="order_month" /> <!-- 列与列之间进行环比计算 --> <cols-chain-relative group-size="3" relative-indexs="1,2" start-column="1" format="#.00%" /></sql>
2.10 分库分表2.10.1 查询分库分表(分库和分表策略可以同时使用) sql参见quickstart项目:com/sqltoy/quickstart/sqltoy-quickstart.sql.xml 文件 <!-- 演示分库 --> <sql id="qstart_db_sharding_case"> <sharding-datasource strategy="hashDataSource" 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="qstart_sharding_table_case"> <sharding-table tables="sqltoy_trans_info_15d" strategy="realHisTable" params="beginDate" /> <value> <![CDATA[ select * from sqltoy_trans_info_15d t where t.trans_date>=:beginDate #[and t.trans_date<=:endDate] ]]> </value> </sql> 2.10.2 操作分库分表(vo对象由quickvo工具自动根据数据库生成,且自定义的注解不会被覆盖)@Sharding 在对象上通过注解来实现分库分表的策略配置 参见:com.sqltoy.quickstart.ShardingSearchTest 进行演示 package com.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;/* * 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)@SqlToyEntitypublic class UserLogVO extends AbstractUserLogVO { private static final long serialVersionUID = 1296922598783858512L; /** default constructor */ public UserLogVO() { super(); }}
全部评论
专题导读
上一篇:redis-admin: 一个简单好用符合国情的redis缓存图形化键值管理工具 ...发布时间:2022-03-24下一篇:DBSyncer: DBSyncer是一款开源的数据同步中间件,提供Mysql、Oracle、SqlServer、Elas ...发布时间:2022-03-24热门推荐
热门话题
阅读排行榜
|
请发表评论