HasorDB 分頁與方言

2022-01-10 14:42 更新

分頁查詢?

HasorDB 內(nèi)置了分頁查詢機制,使用方便且無需任何配置。具體工作方式為:

  • 框架會先生成一條未經(jīng)改寫的最終執(zhí)行 SQL 及參數(shù),并通過 ?BoundSql ?類型承載。
  • 然后會根據(jù) ?PageSqlDialect ?接口將原始 SQL 處理成分頁 SQL。結(jié)果仍然是 ?BoundSql ?類型承載。
  • 執(zhí)行最終的 SQL 完成分頁查詢

LambdaTemplate 方式?

使用 ?LambdaTemplate ?進行分頁查詢

// 構(gòu)造 LambdaTemplate 和初始化一些數(shù)據(jù)
DataSource dataSource = DsUtils.dsMySql();
LambdaTemplate lambdaTemplate = new LambdaTemplate(dataSource);
lambdaTemplate.loadSQL("CreateDB.sql");

// 構(gòu)建分頁對象,每頁 3 條數(shù)據(jù)(默認第一頁的頁碼為 0)
Page pageInfo = new PageObject();
pageInfo.setPageSize(3);

// 分頁查詢數(shù)據(jù)
List<TestUser> pageData1 = lambdaTemplate.lambdaQuery(TestUser.class)
.usePage(pageInfo)
.queryForList();

// 分頁查詢下一頁數(shù)據(jù)
pageInfo.nextPage();
List<TestUser> pageData2 = lambdaTemplate.lambdaQuery(TestUser.class)
.usePage(pageInfo)
.queryForList();

DalSession 方式?

以一個簡單對查詢?yōu)槔?/p>

<select id="queryListByAge">
select * from `test_user` where age = #{age}
</select>

Mapper 無需任何修改,若使用 ?DalSession ?方式執(zhí)行 分頁 Mapper 則需要構(gòu)建分頁對象然后傳遞給 ?queryStatement ?方法。

Map<String, Object> ages = new HashMap<>();
ages.put("age", 26);

PageObject page = new PageObject();
page.setPageSize(20);
List<Object> result = dalSession.queryStatement("queryListByAge", ages, page);

Mapper 接口方式?

首先將 Mapper ?queryListByAge ?方法映射到接口上,然后在接口方法中增加 Page 參數(shù)對象。例如:

@RefMapper("...")
public interface PageExecuteDal {
List<TestUser> queryListByAge(@Param("age") int age, Page pageInfo);
}

或者如下。區(qū)別于上面的是可以選擇返回一個分頁結(jié)果對象 ?PageResult?,分頁結(jié)果對象中包含了分頁信息和總數(shù)數(shù)據(jù)。

提示
使用分頁結(jié)果對象會產(chǎn)生額外的一條 ?count ?查詢。
@RefMapper("...")
public interface PageExecuteDal {
PageResult<TestUser> queryListByAge(@Param("name") String name, Page pageInfo);
}

分頁對象?

HasorDB 提供了一個分頁工具類 ?PageObject?, 它實現(xiàn)了 ?Page ?接口。并提供了如下一些工具屬性/方法。

名稱 描述
屬性 pageSize 頁大小,默認是 -1 表示無窮大
屬性 currentPage 當前頁號
屬性 pageNumberOffset 頁碼偏移量(例如:從1頁作為起始頁,可以設(shè)置為 1。否則第一頁的頁碼是 0)
方法 int getFirstRecordPosition() 獲取本頁第一個記錄的索引位置
方法 int getTotalPage() 獲取總頁數(shù)
方法 int getTotalCount() 獲取記錄總數(shù)
方法 void firstPage() 移動到第一頁
方法 void previousPage() 移動到上一頁
方法 void nextPage() 移動到下一頁
方法 void lastPage() 移動到最后一頁
方法 Map<String, Object> toPageInfo() 獲取分頁信息

?toPageInfo ?方法會返回如下一個 Map。

{
"enable" : true, // 是否啟用分頁
"pageSize" : 20, // 頁大小
"totalCount" : 200, // 總記錄數(shù)
"totalPage" : 10, // 頁總數(shù)
"currentPage" : 0, // 當前頁碼
"recordPosition" : 0// 第一條記錄的起始記錄位置
}

方言?

和方言相關(guān)的接口一共有 4 個,其中 ?SqlDialect ?是所有其它接口都繼承的公共接口。

  • ?SqlDialect ?基礎(chǔ)接口,負責管理關(guān)鍵詞清單、生成表名、列名
  • ?ConditionSqlDialect ?負責條件相關(guān)的生成,例如:like 語句
  • ?InsertSqlDialect ?負責高級 ?insert ?語句生成,例如處理:沖突策略
  • ?PageSqlDialect ?負責分頁語句生成。
提示
實現(xiàn)自定義方言最佳的路線是繼承 ?AbstractDialect ?抽象類,它已經(jīng)實現(xiàn)了 ?SqlDialect?,?ConditionSqlDialect ?兩個接口。

內(nèi)置方言實現(xiàn)?

HasorDB 默認會根據(jù) JDBC 的鏈接字符串自動匹配方言,支持如下數(shù)據(jù)庫:

數(shù)據(jù)庫 編碼 方言類名 JDBC串識別前綴
DB2 db2 Db2Dialect jdbc:db2:***
Apache Derby derby DerbyDialect jdbc:derby:***、jdbc:log4jdbc:derby:***
達夢 dm DmDialect jdbc:dm:***
H2 H2 H2Dialect jdbc:h2::***jdbc:log4jdbc:h2:***
Hive hive HiveDialect jdbc:hive:***、jdbc:hive2:***
HSQL hsql HSQLDialect jdbc:hsqldb:***、jdbc:log4jdbc:hsqldb:***
Apache Impala impala ImpalaDialect jdbc:impala:***
IBM Informix informix InformixDialect jdbc:informix-sqli:***、jdbc:log4jdbc:informix-sqli:***
人大金倉 kingbase KingbaseDialect jdbc:kingbase:***
MariaDB mariadb MariaDBDialect jdbc:mariadb:***
MYSQL mysql MySqlDialect jdbc:mysql:***jdbc:cobar:***、jdbc:log4jdbc:mysql:***
Oracle oracle12c Oracle12cDialect --
Oracle oracle OracleDialect jdbc:oracle:***、jdbc:log4jdbc:oracle:***
Phoenix phoenix PhoenixDialect jdbc:phoenix:***
PostgreSQL postgresql PostgreSqlDialect jdbc:postgresql:***jdbc:log4jdbc:postgresql:***
SQLite sqlite SqlLiteDialect jdbc:sqlite:***
SQL Server sqlserver SqlServer2005Dialect jdbc:microsoft:***、jdbc:log4jdbc:microsoft:***jdbc:sqlserver:***、jdbc:log4jdbc:sqlserver:***
虛谷數(shù)據(jù)庫 xugu XuGuDialect jdbc:xugu:***

自定義方言?

若想實現(xiàn) 分頁方言 自定義只需要繼承 ?AbstractDialect ?抽象類,然后額外在實現(xiàn) ?PageSqlDialect ?接口即可。

?PageSqlDialect ?接口有兩個方法,分別用于生成改寫后的分頁查詢 SQL、以及計算 count 的 SQL。

public interface PageSqlDialect extends SqlDialect {
public default BoundSql countSql(BoundSql boundSql) {
return new BoundSql.BoundSqlObj("SELECT COUNT(*) FROM (" + boundSql.getSqlString() + ") as TEMP_T", boundSql.getArgs());
}

public BoundSql pageSql(BoundSql boundSql, int start, int limit);
}
提示
若計算總數(shù)的 SQL 只是簡單的將其放入子查詢并且 count 一下,那么只實現(xiàn) ?pageSql ?用于改寫分頁語句的 SQL 即可。

使用自己的新方言

對于 ?LambdaTemplate ?類通過下面方式來設(shè)置自己的方言實現(xiàn)類

LambdaTemplate lambdaTemplate = ...
lambdaTemplate.setDialect(new MyDialect());

對于 ?DalSession ?需要通過構(gòu)造方法穿傳入。

DalRegistry dalRegistry = ...
DataSource dataSource = ...
DalSession dalSession = new DalSession(dataSource, dalRegistry, new MyDialect());

通過注冊方式,然后 HasorDB 自動使用新方言。

以 MySQL 為例,MySQL 的鏈接字符串格式為 ?jdbc:mysql:***?

  • 首先 HasorDB 會通過 ?connection.getMetaData().getURL() ?方式拿到鏈接字符串
  • 然后根據(jù)上面 內(nèi)置方言 表格中的信息匹配到對應(yīng)的 ?方言編碼?
  • 最后通過 ?S?qlDialectRegister.findOrCreate(<方言編碼>); ??方法獲取到對應(yīng)的方言對象。

因此只需要按照上面規(guī)則將新的方言注冊到 ?SqlDialectRegister ?上即可。如下:

SqlDialectRegister.registerDialectAlias(JdbcUtils.MYSQL, MyDialect.class);


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號