HasorDB 分页与方言

2022-01-10 14:42 更新

分页查询​

HasorDB 内置了分页查询机制,使用方便且无需任何配置。具体工作方式为:

  • 框架会先生成一条未经改写的最终执行 SQL 及参数,并通过 ​BoundSql ​类型承载。
  • 然后会根据 ​PageSqlDialect ​接口将原始 SQL 处理成分页 SQL。结果仍然是 ​BoundSql ​类型承载。
  • 执行最终的 SQL 完成分页查询

LambdaTemplate 方式​

使用 ​LambdaTemplate ​进行分页查询

// 构造 LambdaTemplate 和初始化一些数据
DataSource dataSource = DsUtils.dsMySql();
LambdaTemplate lambdaTemplate = new LambdaTemplate(dataSource);
lambdaTemplate.loadSQL("CreateDB.sql");

// 构建分页对象,每页 3 条数据(默认第一页的页码为 0)
Page pageInfo = new PageObject();
pageInfo.setPageSize(3);

// 分页查询数据
List<TestUser> pageData1 = lambdaTemplate.lambdaQuery(TestUser.class)
.usePage(pageInfo)
.queryForList();

// 分页查询下一页数据
pageInfo.nextPage();
List<TestUser> pageData2 = lambdaTemplate.lambdaQuery(TestUser.class)
.usePage(pageInfo)
.queryForList();

DalSession 方式​

以一个简单对查询为例:

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

Mapper 无需任何修改,若使用 ​DalSession ​方式执行 分页 Mapper 则需要构建分页对象然后传递给 ​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 参数对象。例如:

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

或者如下。区别于上面的是可以选择返回一个分页结果对象 ​PageResult​,分页结果对象中包含了分页信息和总数数据。

提示
使用分页结果对象会产生额外的一条 ​count ​查询。
@RefMapper("...")
public interface PageExecuteDal {
PageResult<TestUser> queryListByAge(@Param("name") String name, Page pageInfo);
}

分页对象​

HasorDB 提供了一个分页工具类 ​PageObject​, 它实现了 ​Page ​接口。并提供了如下一些工具属性/方法。

名称 描述
属性 pageSize 页大小,默认是 -1 表示无穷大
属性 currentPage 当前页号
属性 pageNumberOffset 页码偏移量(例如:从1页作为起始页,可以设置为 1。否则第一页的页码是 0)
方法 int getFirstRecordPosition() 获取本页第一个记录的索引位置
方法 int getTotalPage() 获取总页数
方法 int getTotalCount() 获取记录总数
方法 void firstPage() 移动到第一页
方法 void previousPage() 移动到上一页
方法 void nextPage() 移动到下一页
方法 void lastPage() 移动到最后一页
方法 Map<String, Object> toPageInfo() 获取分页信息

toPageInfo ​方法会返回如下一个 Map。

{
"enable" : true, // 是否启用分页
"pageSize" : 20, // 页大小
"totalCount" : 200, // 总记录数
"totalPage" : 10, // 页总数
"currentPage" : 0, // 当前页码
"recordPosition" : 0// 第一条记录的起始记录位置
}

方言​

和方言相关的接口一共有 4 个,其中 ​SqlDialect ​是所有其它接口都继承的公共接口。

  • SqlDialect ​基础接口,负责管理关键词清单、生成表名、列名
  • ConditionSqlDialect ​负责条件相关的生成,例如:like 语句
  • InsertSqlDialect ​负责高级 ​insert ​语句生成,例如处理:冲突策略
  • PageSqlDialect ​负责分页语句生成。
提示
实现自定义方言最佳的路线是继承 ​AbstractDialect ​抽象类,它已经实现了 ​SqlDialect​,​ConditionSqlDialect ​两个接口。

内置方言实现​

HasorDB 默认会根据 JDBC 的链接字符串自动匹配方言,支持如下数据库:

数据库 编码 方言类名 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:***
虚谷数据库 xugu XuGuDialect jdbc:xugu:***

自定义方言​

若想实现 分页方言 自定义只需要继承 ​AbstractDialect ​抽象类,然后额外在实现 ​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);
}
提示
若计算总数的 SQL 只是简单的将其放入子查询并且 count 一下,那么只实现 ​pageSql ​用于改写分页语句的 SQL 即可。

使用自己的新方言

对于 ​LambdaTemplate ​类通过下面方式来设置自己的方言实现类

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

对于 ​DalSession ​需要通过构造方法穿传入。

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

通过注册方式,然后 HasorDB 自动使用新方言。

以 MySQL 为例,MySQL 的链接字符串格式为 ​jdbc:mysql:***

  • 首先 HasorDB 会通过 ​connection.getMetaData().getURL() ​方式拿到链接字符串
  • 然后根据上面 内置方言 表格中的信息匹配到对应的 ​方言编码
  • 最后通过 ​S​qlDialectRegister.findOrCreate(<方言编码>); ​​方法获取到对应的方言对象。

因此只需要按照上面规则将新的方言注册到 ​SqlDialectRegister ​上即可。如下:

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


以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号