HasorDB 內(nèi)置了分頁查詢機(jī)制,使用方便且無需任何配置。具體工作方式為:
BoundSql
?類型承載。PageSqlDialect
?接口將原始 SQL 處理成分頁 SQL。結(jié)果仍然是 ?BoundSql
?類型承載。使用 ?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();
以一個(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 ?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);
}
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è)接口。
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:***
?
connection.getMetaData().getURL()
?方式拿到鏈接字符串方言編碼
?S?qlDialectRegister.findOrCreate(<方言編碼>);
??方法獲取到對(duì)應(yīng)的方言對(duì)象。因此只需要按照上面規(guī)則將新的方言注冊(cè)到 ?SqlDialectRegister
?上即可。如下:
SqlDialectRegister.registerDialectAlias(JdbcUtils.MYSQL, MyDialect.class);
更多建議: