<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          sqltoy-ormORM 框架

          聯(lián)合創(chuàng)作 · 2023-09-30 01:40

          sqltoy-orm是比hibernate+myBatis更加貼合項目的orm框架,具有hibernate增刪改的便捷性同時也具有比myBatis更加靈活優(yōu)雅的自定義sql查詢功能。 支持以下數(shù)據(jù)庫:

          • oracle 11g+
          • db2 9.5+,建議從10.5 開始
          • mysql(mariadb/innosql)支持5.6、5.7、8.0 版本
          • postgresql(greenplum) 支持9.5 以及以上版本
          • sqlserver 2012+
          • sqlite
          • DM達夢數(shù)據(jù)庫
          • elasticsearch 只支持查詢,版本支持5.7+版本,建議使用7.3以上版本
          • clickhouse
          • StarRocks(原dorisdb)
          • oceanBase
          • guassdb
          • tidb
          • impala(kudu)
          • kingbase
          • mongodb (只支持查詢)
          • 其他數(shù)據(jù)庫支持基于jdbc的sql執(zhí)行(查詢和自定義sql的執(zhí)行)

          1. 快速特點說明

          1.1 最優(yōu)雅直觀的sql編寫模式

          • sqltoy 的寫法(一眼就看明白sql的本意,后面變更調(diào)整也非常便捷,copy到數(shù)據(jù)庫客戶端里稍做出來即可執(zhí)行)
          • sqltoy條件組織原理很簡單: 如 #[order_id=:orderId] 等于if(:orderId<>null) sql.append(order_id=:orderId);#[]內(nèi)只要有一個參數(shù)為null即剔除
          • 支持多層嵌套:如 #[and t.order_id=:orderId #[and t.order_type=:orderType]]
          • 條件判斷保留#[@if(:param>=xx ||:param<=xx1) sql語句] 這種@if()高度靈活模式,為特殊復(fù)雜場景下提供萬能鑰匙
          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>
              <if test="authedOrganIds!=null">
          	and t.ORGAN_ID in
          	<foreach collection="authedOrganIds" item="order_id" separator="," open="(" close=")">  
                      #{order_id}  
           	</foreach>  
              </if>
              <if test="staffIds!=null">
          	and t.STAFF_ID in
          	<foreach collection="staffIds" item="staff_id" separator="," open="(" close=")">  
                      #{staff_id}  
           	</foreach>  
              </if>
              <if test="beginDate!=null">
          	and t.TRANS_DATE>=#{beginDate}
              </if>
              <if test="endDate!=null">
          	and t.TRANS_DATE<#{endDate}
              </if>
          </where>
          

          1.2 天然防止sql注入,執(zhí)行過程:

          • 假設(shè)sql語句如下
          select 	*
          from sqltoy_device_order_info t 
          where #[t.ORGAN_ID in (:authedOrganIds)]
                #[and t.TRANS_DATE>=:beginDate]
                #[and t.TRANS_DATE<:endDate] 
          • java調(diào)用過程
          sqlToyLazyDao.findBySql(sql, new String[] { "authedOrganIds","beginDate", "endDate"},
          				new Object[] { authedOrganIdAry,beginDate,null}, DeviceOrderInfoVO.class);
          • 最終執(zhí)行的sql是這樣的:
          select 	*
          from sqltoy_device_order_info t 
          where t.ORDER_ID=?
                and t.ORGAN_ID in (?,?,?)
                and t.TRANS_DATE>=?	
          • 然后通過: pst.set(index,value) 設(shè)置條件值,不存在將條件直接作為字符串拼接為sql的一部分

          1.3 最強大的分頁查詢

          1.3.1 分頁特點說明

          • 1、快速分頁:@fast() 實現(xiàn)先取單頁數(shù)據(jù)然后再關(guān)聯(lián)查詢,極大提升速度。
          • 2、分頁優(yōu)化器:page-optimize 讓分頁查詢由兩次變成1.3~1.5次(用緩存實現(xiàn)相同查詢條件的總記錄數(shù)量在一定周期內(nèi)無需重復(fù)查詢)
          • 3、sqltoy的分頁取總記錄的過程不是簡單的select count(1) from (原始sql);而是智能判斷是否變成:select count(1) from 'from后語句', 并自動剔除最外層的order by
          • 4、在極特殊情況下sqltoy分頁考慮是最優(yōu)化的,如:with t1 as (),t2 as @fast(select * from table1) select * from xxx 這種復(fù)雜查詢的分頁的處理,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示例

          <!-- 快速分頁和分頁優(yōu)化演示 -->
          <sql id="sqltoy_fastPage">
          	<!-- 分頁優(yōu)化器,通過緩存實現(xiàn)查詢條件一致的情況下在一定時間周期內(nèi)緩存總記錄數(shù)量,從而無需每次查詢總記錄數(shù)量 -->
          	<!-- alive-max:最大存放多少個不同查詢條件的總記錄量; alive-seconds:查詢條件記錄量存活時長(比如120秒,超過閥值則重新查詢) -->
          	<page-optimize parallel="true" alive-max="100" alive-seconds="120" />
          	<value>
          		<![CDATA[
          		select t1.*,t2.ORGAN_NAME 
          		-- @fast() 實現(xiàn)先分頁取10條(具體數(shù)量由pageSize確定),然后再關(guān)聯(lián)
          		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來實現(xiàn)極致性能優(yōu)化 -->
          	<!-- <count-sql></count-sql> -->
          </sql>

          1.3.3 分頁java代碼調(diào)用

          /**
           *  基于對象傳參數(shù)模式
           */
          public void findPageByEntity() {
          	Page pageModel = new Page();
          	StaffInfoVO staffVO = new StaffInfoVO();
          	// 作為查詢條件傳參數(shù)
          	staffVO.setStaffName("");
          	// 使用了分頁優(yōu)化器
          	// 第一次調(diào)用:執(zhí)行count 和 取記錄兩次查詢
          	Page result = sqlToyLazyDao.findPageBySql(pageModel, "sqltoy_fastPage", staffVO);
          	System.err.println(JSON.toJSONString(result));
          	// 第二次調(diào)用:過濾條件一致,則不會再次執(zhí)行count查詢
          	//設(shè)置為第二頁
          	pageModel.setPageNo(2);
          	result = sqlToyLazyDao.findPageBySql(pageModel, "sqltoy_fastPage", staffVO);
          	System.err.println(JSON.toJSONString(result));
          }
          
          /**
           *  基于參數(shù)數(shù)組傳參數(shù)
           */
          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 最巧妙的緩存應(yīng)用,將多表關(guān)聯(lián)查詢盡量變成單表(看下面的sql,如果不用緩存翻譯需要關(guān)聯(lián)多少張表?sql要有多長?多難以維護?)

          • 1、 通過緩存翻譯: 將代碼轉(zhuǎn)化為名稱,避免關(guān)聯(lián)查詢,極大簡化sql并提升查詢效率
          • 2、 通過緩存名稱模糊匹配: 獲取精準(zhǔn)的編碼作為條件,避免關(guān)聯(lián)like 模糊查詢
          <sql id="sqltoy_order_search">
          	<!-- 緩存翻譯設(shè)備類型
                  cache:具體的緩存定義的名稱,
                  cache-type:一般針對數(shù)據(jù)字典,提供一個分類條件過濾
          	columns:sql中的查詢字段名稱,可以逗號分隔對多個字段進行翻譯
          	cache-indexs:緩存數(shù)據(jù)名稱對應(yīng)的列,不填則默認為第二列(從0開始,1則表示第二列),
          	      例如緩存的數(shù)據(jù)結(jié)構(gòu)是: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,-- 設(shè)備分類名稱
          		STAFF_ID,
          		STAFF_ID staffName, -- 員工姓名
          		ORGAN_ID,
          		CREATE_BY,
          		CREATE_BY createName -- 創(chuàng)建人名稱
          	from sqltoy_device_order_info t 
          	where #[t.ORDER_ID=:orderId]
          	      #[and t.STAFF_ID in (:staffIds)]
          		]]>
          	</value>
          </sql>

          最跨數(shù)據(jù)庫

          • 1、提供類似hibernate性質(zhì)的對象操作,自動生成相應(yīng)數(shù)據(jù)庫的方言。
          • 2、提供了最常用的:分頁、取top、取隨機記錄等查詢,避免了各自不同數(shù)據(jù)庫不同的寫法。
          • 3、提供了樹形結(jié)構(gòu)表的標(biāo)準(zhǔn)鉆取查詢方式,代替以往的遞歸查詢,一種方式適配所有數(shù)據(jù)庫。
          • 4、sqltoy提供了大量基于算法的輔助實現(xiàn),最大程度上用算法代替了以往的sql,實現(xiàn)了跨數(shù)據(jù)庫
          • 5、sqltoy提供了函數(shù)替換功能,比如可以讓oracle的語句在mysql或sqlserver上執(zhí)行(sql加載時將函數(shù)替換成了mysql的函數(shù)),最大程度上實現(xiàn)了代碼的產(chǎn)品化。 default:SubStr\Trim\Instr\Concat\Nvl 函數(shù);可以參見org.sagacity.sqltoy.plugins.function.Nvl 代碼實現(xiàn)
                 <!-- 跨數(shù)據(jù)庫函數(shù)自動替換(非必須項),適用于跨數(shù)據(jù)庫軟件產(chǎn)品,如mysql開發(fā),oracle部署 -->
             <property name="functionConverts" value="default">
             <!-- 也可以這樣自行根據(jù)需要進行定義和擴展
             <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> -->
          </bean>
          

          1.5 提供行列轉(zhuǎn)換(數(shù)據(jù)旋轉(zhuǎn)),避免寫復(fù)雜的sql或存儲過程,用算法來化解對sql的高要求,同時實現(xiàn)數(shù)據(jù)庫無關(guān)(不管是mysql還是sqlserver)

                  <!-- 列轉(zhuǎn)行測試 -->
          	<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:企業(yè)金額"
          			values-as-column="TRANS_AMOUNT" labels-as-column="AMOUNT_TYPE" />
          	</sql>
          
          	<!-- 行轉(zhuǎn)列測試 -->
          	<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避免跨數(shù)據(jù)庫語法不一致)

          	<!-- 匯總計算 (場景是sql先匯總,頁面上還需要對已有匯總再匯總的情況,如果用sql實現(xiàn)在跨數(shù)據(jù)庫的時候就存在問題)-->
          	<sql id="sys_summarySearch">
          		<!-- 數(shù)據(jù)源sharding,多庫將請求壓力分攤到多個數(shù)據(jù)庫節(jié)點上,支撐更多并發(fā)請求 -->	
          		<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 作為分庫關(guān)鍵字段屬于必備條件
          			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工具自動根據(jù)數(shù)據(jù)庫生成,且自定義的注解不會被覆蓋)

          @Sharding 在對象上通過注解來實現(xiàn)分庫分表的策略配置

          參見: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表示要以對象的哪幾個字段值作為判斷依據(jù),可以一個或多個字段
           * maxConcurrents:可選配置,表示最大并行數(shù) maxWaitSeconds:可選配置,表示最大等待秒數(shù)
           */
          @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();
          	}
          }
          
          瀏覽 4
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          編輯 分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          編輯 分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  高清无码免费 | 亚洲欧美电影 | 婷婷国产wwww | 影音先锋日韩无码 | 麻豆传媒操逼表情包 |