HasorDB 分頁與方言

2022-01-10 14:42 更新

分頁查詢?

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

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

LambdaTemplate 方式?

使用 ?LambdaTemplate ?進(jìn)行分頁查詢

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

// 構(gòu)建分頁對(duì)象,每頁 3 條數(shù)據(jù)(默認(rèn)第一頁的頁碼為 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 方式?

以一個(gè)簡(jiǎn)單對(duì)查詢?yōu)槔?/p>

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

Mapper 無需任何修改,若使用 ?DalSession ?方式執(zhí)行 分頁 Mapper 則需要構(gòu)建分頁對(duì)象然后傳遞給 ?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ù)對(duì)象。例如:

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

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

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

分頁對(duì)象?

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

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

?toPageInfo ?方法會(huì)返回如下一個(gè) Map。

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

方言?

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

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

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

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

數(shù)據(jù)庫 編碼 方言類名 JDBC串識(shí)別前綴
DB2 db2 Db2Dialect jdbc:db2:***
Apache Derby derby DerbyDialect jdbc:derby:***jdbc:log4jdbc:derby:***
達(dá)夢(mèng) 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:***

自定義方言?

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

?PageSqlDialect ?接口有兩個(gè)方法,分別用于生成改寫后的分頁查詢 SQL、以及計(jì)算 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);
}
提示
若計(jì)算總數(shù)的 SQL 只是簡(jiǎn)單的將其放入子查詢并且 count 一下,那么只實(shí)現(xiàn) ?pageSql ?用于改寫分頁語句的 SQL 即可。

使用自己的新方言

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

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

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

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

通過注冊(cè)方式,然后 HasorDB 自動(dòng)使用新方言。

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

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

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

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


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

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)