HasorDB 分頁(yè)與方言

2022-01-10 14:42 更新

分頁(yè)查詢?

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

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

LambdaTemplate 方式?

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

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

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

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

// 分頁(yè)查詢下一頁(yè)數(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 無(wú)需任何修改,若使用 ?DalSession ?方式執(zhí)行 分頁(yè) Mapper 則需要構(gòu)建分頁(yè)對(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è)分頁(yè)結(jié)果對(duì)象 ?PageResult?,分頁(yè)結(jié)果對(duì)象中包含了分頁(yè)信息和總數(shù)數(shù)據(jù)。

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

分頁(yè)對(duì)象?

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

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

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

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

方言?

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

  • ?SqlDialect ?基礎(chǔ)接口,負(fù)責(zé)管理關(guān)鍵詞清單、生成表名、列名
  • ?ConditionSqlDialect ?負(fù)責(zé)條件相關(guān)的生成,例如:like 語(yǔ)句
  • ?InsertSqlDialect ?負(fù)責(zé)高級(jí) ?insert ?語(yǔ)句生成,例如處理:沖突策略
  • ?PageSqlDialect ?負(fù)責(zé)分頁(yè)語(yǔ)句生成。
提示
實(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ù)庫(kù):

數(shù)據(jù)庫(kù) 編碼 方言類名 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:***
人大金倉(cāng) 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ù)庫(kù) xugu XuGuDialect jdbc:xugu:***

自定義方言?

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

?PageSqlDialect ?接口有兩個(gè)方法,分別用于生成改寫后的分頁(yè)查詢 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 ?用于改寫分頁(yè)語(yǔ)句的 SQL 即可。

使用自己的新方言

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

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

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

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

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

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

  • 首先 HasorDB 會(huì)通過(guò) ?connection.getMetaData().getURL() ?方式拿到鏈接字符串
  • 然后根據(jù)上面 內(nèi)置方言 表格中的信息匹配到對(duì)應(yīng)的 ?方言編碼?
  • 最后通過(guò) ?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)