自用为主,beetlsql是现在实习公司里用的,官网的文档有点乱。。然后找到了个比较好的文档,大部分来源于那篇文档,不过这里也加入了一些我自己的理解
BeetlSql是一个数据访问框架,目标是提供开发敏捷,维护边界,运行告诉的数据库访问框架,目标是代替传统的JPA、Mybatis、Hibernate
传统数据库:MySQL,MariaDB,Oralce,Postgres,DB2,SQL Server,H2,SQLite,Derby,神通,达梦,华为高斯,人大金仓,PolarDB,万里开源GreatSQL,南大通用GBase8s等
大数据:HBase,ClickHouse,Cassandar,Hive
物联网时序数据库:Machbase,TD-Engine,IotDB
SQL查询引擎:Drill,Presto,Druid
内存数据库:ignite,CouchBase
派别:SQL为中心
内置常见增删改查功能,节省项目50%工作量
强化SQL管理,通过md文件管理sql,使用Beetl模板编写复杂sql
简单SQL可以通过Query类链式API完成
全面支持跨数据库平台
支持NOSQL,如ClickhHouse,Elastic,Hive等
支持SQL查询引擎,如Apache Drill,Presto等
支持一对一,一对多等常见的映射。
可以使用约定习俗映射,复杂查询结果支持通过json配置映射到POJO
提供idea插件
其他
具备代码生成功能,提供代码生成框架
最大程度减少数据库重构对项目造成的影响
最大程度减少数据库切换对项目造成的影响
支持多数据源,数据源包含传统数据库,NOSQL,SQL查询引擎,且可以根据规则使用数据源
内置主从支持
提供丰富的扩展功能,80%的功能都可以自行扩展,打造自己个性化的数据库发访问框架,扩展适应新的数据库&NOSQL&查询引擎
开发效率低,如mybatis,还需要搭配plus工具才能提高开发效率,而JOOQ这样的又不适合复杂访问
无SQL管理,遇到复杂的sql特别难维护,比如在Java里拼写sql,遇到调整就麻烦
跨数据库平台,即使Hibernate,也完全做不到跨数据库
缺少数据库和NOSQL无缝切换很难,比如一部分业务要无缝切换到NOSQL上
数据库重构对代码影响非常大,数据库列修改,增加要改很多代码
难以调试数据库访问代码
com.ibeetl
sql-springboot-starter
3.9.0-RELEASE
org.springframework.boot
spring-boot-starter-jdbc
mysql
mysql-connector-java
com.alibaba
druid-spring-boot-starter
1.2.6
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(64) DEFAULT NULL,
`age` int(4) DEFAULT NULL,
`create_date` datetime NULL DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
/**
* 与数据库 user 表对应的 POJO
*/
@Data
public class User {
private Integer id ;
private Integer age ;
private String name ;
private Date createDate ;
}
3.3.1 Entity
最常用实体类,基本和数据表一一对应,一个实体一张表。
3.3.2 Pojo类
Pojo“Plain Old Java Object”
简单的Java对象。
纯的传统意义的java对象,最基本的Java Bean只有属性加上属性的get和set方法
3.3.3 DTO(data transfer object)
代表数据传输对象的意思
是一种设计模式之间传输数据的软件应用系统,数据传输目标往往是数据访问对象从数据库中检索数据
数据传输对象与数据交互对象或数据访问对象之间的差异是一个以不具任何行为除了存储和检索的数据(访问和存取器)
简而言之,就是接口之间传递的数据封装
表里面有十几个字段:id,name,gender(M/F),age……
页面需要展示三个字段:name,gender(男/女),age
DTO由此产生,一是能提高数据传输的速度(减少了传输字段),二能隐藏后端表结构
3.3.4 Vo(value object)
代表值对象的意思,通常用于业务层之间的数据传递,由new创建,由GC回收。 主要体现在视图的对象,对于一个WEB页面将整个页面的属性封装成一个对象,然后用一个VO对象在控制层与视图层进行传输交换。
3.3.5Po(persistant object)
代表持久层对象的意思,对应数据库中表的字段,数据库表中的记录在java对象中的显示状态,最形象的理解就是一个PO就是数据库中的一条记录。
好处是可以把一条记录作为一个对象处理,可以方便的转为其它对象。Vo和Po,都是属性加上属性的get和set方法;表面看没什么不同,但代表的含义是完全不同的。
3.3.6 Bo(business object)
代表业务对象的意思,Bo就是把业务逻辑封装为一个对象(注意是逻辑,业务逻辑),这个对象可以包括一个或多个其它的对象。通过调用Dao方法,结合Po或Vo进行业务操作。
形象描述为一个对象的形为和动作,当然也有涉及到基它对象的一些形为和动作。比如处理一个人的业务逻辑,该人会睡觉,吃饭,工作,上班等等行为,还有可能和别人发关系的行为,处理这样的业务逻辑时,我们就可以针对BO去处理。
再比如投保人是一个Po,被保险人是一个Po,险种信息也是一个Po等等,他们组合起来就是一张保单的B o。
3.3.7 Dao(data access object)
代表数据访问对象的意思,是sun的一个标准j2ee设计模式的接口之一,负责持久层的操作 。这个基本都了解,Dao和上面几个O区别最大,基本没有互相转化的可能性和必要,主要用来封装对数据的访问,注意,是对数据的访问,不是对数据库的访问。
3.3.8 Controller
代表数据访问对象的意思,是sun的一个标准j2ee设计模式的接口之一,负责持久层的操作 。这个基本都了解,Dao和上面几个O区别最大,基本没有互相转化的可能性和必要,主要用来封装对数据的访问,注意,是对数据的访问,不是对数据库的访问。
3.3.9 View
代表视图层的意思,主要是指由JSP、HTML等文件形成的显示层。
所以实际项目中,一般都是这样应用的: 控制层(controller-action),业务层/服务层( bo-manager-service),实体层(po-entity),dao(dao),视图对象(Vo-),视图层(view-jsp/html)
mapper继承BaseMapper
例子:
public interface UserMapper extends BaseMapper {
}
UserMapper的关系
BaseMapper 具备很多内置的 CRUD 方法,因此有了 UserMapper 后,同样可以不写任何 SQL,可以轻易的完成常用操作 我们可以将UserMapper
注入,然后调用它的方法完成 CRUD
下面列举几个常用方法:
方法 | 说明 |
---|---|
void insert(T entity) |
通用插入,插入一个实体对象到数据库 |
void insertTemplate(T entity) |
插入实体到数据库,对于 null 值不做处理 |
int updateById(T entity) |
据主键更新对象,所以属性都参与更新 |
boolean upsert(T entity) |
按照主键更新更新或插入,自增或者序列 id 自动赋值给 entity |
int deleteById(Object key) |
根据主键删除对象,如果对象是复合主键,传入对象本生即可 |
T single(Object key) |
根据主键获取对象,如果对象不存在,返回 null |
还有更多... | 更多 BaseMapper 内置方法使用参见 BaseMapper.java |
注意:使用LamdbaQuery
(推荐) 必须使用 Java8 及以上版本。
获取 Query 查询器
我们继续以 user 表为例
取得Query
有多种方式
// 方式一:注入 mapper 后用 mapper 获取
userMapper.createLambdaQuery();
// 方式二:注入 sqlManage 后用 sqlmanage 获取 (指定类型)
Query query = sqlManage.lambdaQuery(User.class);
// 方式三:注入 sqlManage 后用 sqlmanage 获取 (指定类型)
Query query = sqlManager.query(User.class);
查询模糊查询用户名包含"t",delete_time 不为空的数据,按照 id 倒序
// 代码中直接使用 userMapper 查询
List userList = userMapper.createLambdaQuery()
.andLike(User::getName,"%t%")
.andIsNotNull(User::getDeleteTime)
.desc(User::getId)
.select();
从上面的例子可以看出,Query 是使用链式调用,看起来就像一个完整的 sql 一般,使用方式遵从用户平时 SQL 编写习惯。
所有的条件列完之后,再调用操作方法(要执行的方法:select
,insert
,update
,page
, count
等等)
查询指定字段
如果我们只要查询表其中的几个字段怎么办?如我只要 name 和 id 字段:
// 用法一 (推荐)
userMapper.createLambdaQuery()
.select(User::getName,User::getId);
// 用法二
userMapper.createLambdaQuery()
.select("name","id");
复杂的条件查询
要进行一条复杂的条件查询 SQL,需要用到 query.condition()
方法,产生一个新的条件,比如我们要查询下面这条 SQL
SELECT * FROM `user`
WHERE ( `id` IN( 100 , 101 , 102 )
AND `name` LIKE '%t%' ) OR ( `id` = 10086 )
userMapper.createLambdaQuery()
.or(query.condition()
.andIn("id", Arrays.asList(100, 101, 102))
.andLike("name", "%t%"))
.or(query.condition().andEq("id", 10086))
.select();
查询字段智能判断是否为空
我们开发中,经常会遇到前端传过来一些搜索条件,后端根据搜索条件进行判断,不为空时加入查询条件。 例如前端一个用户列表,有一个根据用户名进行查询的搜索框,我们一般会这么写。
public User findUser(String userName){
LambdaQuery query = sqlManager.lambdaQuery(User.class);
query.andEq(User::getDeleteFlag,0);
if(StringUtil.isNotEmpty(userName)) {
query.andEq(User::getUserName,userName);
}
return query.single();
}
如果有很多个这样的字段查询,会显得比较臃肿,beetlsql 很好的解决了这个问题。
Query 工具中内置了两个过滤值的静态方法,filterEmpty
、filterNull
,这两个方法返回了一个StrongValue
对象。
filterEmpty
方法主要作用是,当一个字段为空时不把他加入查询条件,当字段不为空时才加入查询条件。
为空的判断标准:
当字段为 String 类型,会判断空字符串以及 NULL。
当字段为 Collection 类型以及其子类时,会调用 isEmpty 方法判断,以及 NULL。
当字段为其他对象时,仅仅会判断 NULL。
要实现上面的代码,我们只要下面这样写就行了:
public User findUser(String userName){
LambdaQuery query = sqlManager.lambdaQuery(User.class);
return query.andEq(User::getDeleteFlag,0)
.andEq(User::getUserName,Query.filterEmpty(userName))
.single();
}
如果 userName 有值的情况下,例如等于"myName",将会生成下面的语句:
select * from user where delete_flag = 0
and user_name = "myName"
limit 0,1
当 userName 为空字符串或者 NULL 的时候,user_name 将不会参与条件查询:
select * from user where delete_flag = 0
limit 0,1
filterNull 方法的作用也是类似的,但是此方法只会判断对象是否等于 NULL
自定义实现
但是业务场景往往是复杂的,BeetSql 也提供了非常好的拓展性,filterEmpty
,filterNull
可以 自定义实现
全量插入
User record = new User();
record.setName("new name");
Query query = sqlManager.lambdaQuery(User.class);
int count = query.insert(record);
全量插入,会对所有的值进行插入,即使这个值是 NULL;返回影响的行数
选择字段插入
User record = new User();
record.setName("new name2");
record.setCreateTime(new Date());
Query query = sqlManager.lambdaQuery(User.class);
int count = query.insertSelective(record);
insertSelective
方法,对 null 值的字段不插入;返回影响的行数
update 和 insert 类似,有全量更新和选择列更新的方法;
全量更新 update 方法
User record = new User();
record.setName("new name");
Query query = sqlManager.query(User.class);
int count = query.andEq("id", 1637)
.andLess("create_time", new Date())
.andEq("name", "test")
.update(record);
全量更新,会对所有的值进行更新,即使这个值是 null;返回影响的行数;
选择更新
User record = new User();
record.setName("new name");
Query query = sqlManager.query(User.class);
int count = query.andEq("id", 1637)
.andLess("create_time", new Date())
.andEq("name", "test")
.updateSelective(record);
updateSelective
方法,对 user 进行了一次有选择性的更新。非 null 值更新,null 值不更新;返回影响的行数;
Query query = sqlManager.query(User.class);
int count = query.andEq("id", 1642)
.delete();
delete 操作非常简单,拼接好条件,调用 delete 方法即可;返回影响的行数。
在 beetlSql 中还提供了两个用来查询单条数据的方法,single 和 unique;
single 单条查询
single 查询,查询出一条,如果没有,返回 null;
Query query = sqlManager.query(User.class);
User user = query.andEq("id", 1642).single();
unique 单条查询
unique 查询和 single 稍微不同,只能查询一条,如果没有或者有多条,抛出异常
Query query = sqlManager.query(User.class);
User user = query.andEq("id", 1642).single();
如果存在多条,或者没有则抛出异常:org.beetl.sql.core.BeetlSQLException
count 查询主要用于统计行数,如下面的 SQL:
SELECT COUNT(1) FROM `user` WHERE `name` = 'myName' OR `id` = 1637 limit 0 , 10
Query query = sqlManager.query(User.class);
long count = query.andEq("name", "new name")
.orEq("id", 1637).limit(1, 10)
.count();
拼接条件,调用 count 方法,返回总行数。
有时候我们要进行分组查询,如以下 SQL:
SELECT * FROM `user` WHERE `id` IN(1637, 1639, 1640 ) GROUP BY name
在 BeetlSql 中直接拼条件调用 group 方法,传入字段即可:
Query query = sqlManager.query(User.class);
List list = query
.andIn("id", Arrays.asList(1637, 1639, 1640))
.groupBy("name")
.select();
在分组查询之后,我们可能还要进行 having 筛选,只需要在后面调用 having 方法,传入条件即可。
SELECT * FROM `user` WHERE `id` IN( 1637, 1639, 1640 ) GROUP BY name HAVING `create_time` IS NOT NULL
Query query = sqlManager.query(User.class);
List list = query
.andIn("id", Arrays.asList(1637, 1639, 1640))
.groupBy("name")
.having(query.condition().andIsNotNull("create_time"))
.select();
进行排序查询时,只要调用 orderBy 方法,传入要排序的字段以及排序方式即可。
SELECT * FROM `user` WHERE `id` BETWEEN 1 AND 1640
AND `name` LIKE '%t%'
AND `create_time` IS NOT NULL ORDER BY id desc
Query query = sqlManager.query(User.class);
List list = query.andBetween("id", 1, 1640)
.andLike("name", "%t%")
.andIsNotNull("create_time")
.orderBy("id desc").select();
query 接口分为两类
查询和更新操作
select
触发查询,返回指定的对象列表
single
触发查询,返回一个对象,如果没有,返回 null
unique
触发查询,返回一个对象,如果没有,或者有多个,抛出异常
count
对查询结果集求总数
delete
删除符合条件的结果集
update
全部字段更新,包括更新 null 值
updateSelective
更新选中的结果集(null 不更新)
insert
全部字段插入,包括插入 null 值
insertSelective
有选择的插入,null 不插入
各种条件
标准 sql 操作符 | and 操作 | or 操作 |
---|---|---|
==,!= | andEq,andNotEq | orEq,orNotEq |
>,>= | andGreat,andGreatEq | orGreat,orGreatEq |
<,<= | andLess,andLessEq | orLess,orLessEq |
LIKE,NOT LIKE | andLike,andNotLike | orLike,orNotLike |
IS NULL,IS NOT NULL | andIsNull,andIsNotNull | orIsNull,orIsNotNull |
IN,NOT IN | andIn ,andNotIn | orIn,orNotIn |
BETWEEN ,NOT BETWEEN | andBetween,andNotBetween | orBetween,orNotBetween |
AND | ( .....) | and or |
标准 sql | Query 方法 |
---|---|
限制结果结范围,依赖于不同数据库翻页 | limit (默认从 1 开始,会自动处理) |
ORDER BY | orderBy, desc,asc |
GROUP BY | groupBy |
HAVING | having |
使用@sql注解提供一个Sql语句
使用示例
public interface UserMapper extends BaseMapper {
@Sql("select * from sys_user where id = ?")
User queryUserById(Integer id);
@Sql("update sys_user set name=? where id = ?")
@Update
int updateName(String name,Integer id);//更新方法
}
在UserMapper中定义了queryUserById方法,并且使用@sql提供一个sql语句 那么我们可以在注入UserMapper后调用此方法
@Autowired
UserMapper userMapper;
@RequestMapping("test")
public String test() {
User user = userMapper.queryUserById(100);
}
需要显示的使用@Update
注解表明是一个更新或删除类的 sql,@BatchUpdate
注解表明是一个批量更新 sql
使用@Select
注解表明是一个查询 Sql(默认行为,所以可省略)
@Sql
注解的方法参数返回值取决于于 sql 查询结果,不限定于 Mapper 定义的泛型,可以是任意 POJO
使用@Template注解和@Sql类似
public interface UserMapper extends BaseMapper {
@Template("select * from sys_user where id = #{id}")
User queryUserById(Integer id);
}
/**
*@Sql占位符是 ?
@Template占位符是 #{}
*/
调用方法
@Autowired
UserMapper userMapper;
@RequestMapping("test")
public String test() {
User user = userMapper.queryUserById(100);
}
@Template
注解的方法参数返回值取决于于 sql 查询结果,不限定于 Mapper 定义的泛型,可以是任意 POJO
使用 Markdown 文件组织 sql 方式和注解相同的地方都是在 Mapper 里定义方法,方法上不加@Sql
或@Template
即可 所有 Markwown 的 sql 文件默认位于 classpath 的 sql 目录下。一个 sql 文件里可以写多个 sql 片段
XML 格式过于复杂,书写不方便
XML 格式有保留符号,写 SQL 的时候不方便,如常用的< 符号 必须转义
md 格式本身就是一个文档格式,容易通过浏览器和各种开发工具阅读和编辑维护
md 中的 sql 语句是一个整体,可以直接复制出来执行,XML 无法做到
public interface UserMapper extends BaseMapper {
// 定义方法,不加 @Sql 或 @Template 注解,BeetlSQL 就会去 markdown 文件查找 sql
User queryUserById(Integer id);
}
在resources/sql/
文件夹下新建 user.md 写 sql
使用===
作为分隔,===
上方是 sql 片段名称 (要与 mapper 中的方法名相同),===
下方是 sql 语句,切记名称后不要有空格或者任何不可见的符号,否则 BeetlSQL 找不到
SQL 名称
===
以 * 开头的注释
SQL 语句
SQL 名称 2
===
SQL 语句 2
queryUserById
===
```sql
select * from sys_user where id = #{id}
```
markdown 中使用```sql是可选的,好处在于帮助 IDE 或者其他工具能对 sql 进行 ==高亮== 和语法校验
POJO,mapper 接口,markdown 之间的关系如下图所示
beetlsql:
# sqlManage,可以配置多个,用逗号隔开
sqlManagers: sqlManager1,sqlManager2
# sqlManage1 的配置
sqlManager1:
# 数据源名称
ds: dataSource
# 指明 mapper 类的结尾,扫描到以 Mapper 结尾的类会为其自动生成代理类,注册为 Spring 的 Bean
# 默认扫描 Mapper 结尾,可不配置。如果你不是 xxxMapper 这样以 Mapper 结尾的,则需要配置
daoSuffix: Dao
# 要扫描 Mapper 的包名
basePackage: com.compamny.xxxx
# POJO 和数据表列的名称转换,如驼峰 userName 转换为下划线的 user_name
nameConversion: org.beetl.sql.core.UnderlinedNameConversion
# 数据库方言
dbStyle: org.beetl.sql.core.db.MySqlStyle
# 是否是开发模式
dev: true
# 存放 sql 文件的根目录,默认就是 resources/sql/下,所以可以不配置,
sqlPath: sql
# sql 文件编码
sqlFileCharset: utf-8
sqlManager2:
同上,省略...
数据库 | 配置值 |
---|---|
Mysql | org.beetl.sql.core.db.MySqlStyle |
Oracle | org.beetl.sql.core.db.OracleStyle |
Postgres | org.beetl.sql.core.db.PostgresStyle |
SqlServer | org.beetl.sql.core.db.SqlServerStyle |
SQLite | org.beetl.sql.core.db.SQLiteStyle |
ShenTongSql | org.beetl.sql.core.db.ShenTongSqlStyle |
PolarDB | org.beetl.sql.core.db.PolarDBStyle |
OpenGauss | org.beetl.sql.core.db.OpenGaussStyle |
Kingbase | org.beetl.sql.core.db.KingbaseStyle |
H2 | org.beetl.sql.core.db.H2Style |
DB2Sql | org.beetl.sql.core.db.DB2SqlStyle |
可选值 | 说明 |
---|---|
org.beetl.sql.core.UnderlinedNameConversion |
默认值,下划线命名转换,数据库 Sys_User,对应类 SysUser,列 user_Id,对应属性 userId |
org.beetl.sql.core.DefaultNameConversion |
数据库命名完全按照 java 风格来,数据库表 SysUser,对应类 SysUser,列 userId,对应属性 userId |
在 Spring Boot 中sqlManage
由 starter 装配,我们可以通过SQLManagerCustomize
接口来修改
比如修改默认的日志拦截器
@Configuration
public class BeeConfig {
@Bean
public SQLManagerCustomize sqlManagerCustomize() {
return (sqlManagerName, manager) -> {
// 设置 sql 拦截器
manager.setInters(new Interceptor[]{new Slf4JLogInterceptor()});
};
}
}
@Table 注解用在 POJO 上,用于数据库表名和 POJO 名称不一致的情况
例如表名为tb_user
, POJO 为User
,则添加@Table(name = "tb_user")
注解,将表tb_user
和User
对应
@Data
@Table(name = "tb_user")
public class User {
private Integer id ;
private Integer age ;
private String name ;
private Date createDate ;
}
用于在 POJO 中指定数据库主键类型
注解 | 说明 |
---|---|
@AutoID |
作用于属性字段或者 getter 方法,告诉 beetlsql,这是自增主键,对应于数据自增长 |
@AssignID |
作用于属性字段或者 getter 方法,告诉 beetlsql,这是程序指定主键 |
@SeqID |
作用于 getter 方法,告诉 beetlsql,这是序列主键 |
@Data
public class User {
@AutoID // 指明表的 id 列是自增
private Integer id ;
private Integer age ;
private String name ;
private Date createDate ;
}
@AssignID
代码设定主键可以传入 id 的生成策略以自动生成序列
beetl 默认提供了 snowflake 算法,一个用于分布式环境的 id 生成器
@AssignID("simple")
public Long getId() {
return id;
}
simple 是 beetlsql 提供的一个默认的 snowflake 实现,你可以通过 sqlManager 自己注册 id 生成器
sqlManager.addIdAutonGen("uuid2", new IDAutoGen(){
@Override
public Object nextID(String params) {
return "hi"+new Random().nextInt(10000);
}
});
@AssignID("uuid2")
public Long getId() {
return id;
}
通常数据库列名和实体类对应关系已经由 NameConversion 转化好了,如果你有特殊的命名需求,可以使用此注解
@Data
public class User {
@AutoID // 指明表的 id 列是自增
private Integer id ;
@Colum("my_age")
private Integer age ;
private String name ;
private Date createDate ;
}
使用@Colum("my_age")
后age
字段可以对应到 user 数据表中的my_age
列
@SqlResource
@SqlResource
注解在 Mapper 上,指明 sql 片段所在的文件,如没有使用此注解,则会默认通过泛型类来查找,规则是泛型类名的首字母小写作为文件名
@SqlResource("myUser")
public interface UserMapper extends BaseMapper {
List selectByName(String name);
}
如果未使用@SqlResource
则去resources/sql/
下找user.md
使用@SqlResource("myUser")
后则去resources/sql/
下找myUser.md
@SpringData
@SpringData
模仿了 Spring Data 中通过方法名解析出 sql 语句的功能,比如 findById,则表示根据 id 属性查询。findByNameAndAgeOrderByIdDesc,则表示根据 name 和 age 属性查询,且输出结果按照 Id 降序排序。
要了解 BeetlSQL3 支持的所有 Spring Data 关键字,可以查看 SpringDataBuilder (opens new window)类,或参考 Spring Data 文档
分页查询是我们经常要使用的功能,beetlSql 支持多数据,会自动适配当前数据库生成分页语句
LambdaQuery.limit()
分页查询public interface UserMapper extends BaseMapper {
}
调用:
@Autowired
UserMapper userMapper;
/**
* 查询用户
*/
@RequestMapping("page")
public String page() {
PageResult result = userMapper.createLambdaQuery()
.andLike(User::getName,"%t%")
.andIsNotNull(User::getDeleteTime)
.desc(User::getId)
.limit(1, 10);
}
LambdaQuery.page()
分页查询@Autowired
UserMapper userMapper;
/**
* 查询用户
*/
@RequestMapping("page")
public String page() {
PageResult result = userMapper.createLambdaQuery()
.andLike(User::getName,"%t%")
.andIsNotNull(User::getDeleteTime)
.desc(User::getId)
.page(1, 10);
}
page()
中传入起始页和查询条数即可
返回值PageResult
包含了查询到的列表数据和总条数
List list = result.getList();
long totalRow = result.getTotalRow();
更常用的是传入一个PageRequest
对象,通过PageRequest
对象可以构造更多选项
比如
totalRequired 是否需要查询总条数
orderBy 排序方式
PageResult result = userDao.createLambdaQuery()
.page(DefaultPageRequest.of(1,10));
page 方法还有很多重载方法,具体使用参见代码
使用page()
函数指明分页查询,PageRequest
是分页参数
public interface UserMapper extends BaseMapper {
@Template("select #{page()} from sys_user where department_id = #{id}")
PageResult pageQueryById(Integer id,PageRequest pageRequest);
}
pageTag()
public interface UserMapper extends BaseMapper {
PageResult pageTest(PageRequest query);
}
pageTest
===
```sql
select
-- @{pageTag()
name, age
-- @}
from user
```
Lombok 是一种 Java™ 实用工具,可用来帮助开发人员消除 Java 的冗长,尤其是对于简单的 Java 对象(POJO)。它通过注解实现这一目的。
要使用这个对象,必须还要写一些getter和setter方法,可能还要写一个构造器、equals方法、或者hash方法.这些方法很冗长而且没有技术含量,我们叫它样板式代码.
@Data : 加在类上,相当于同时使用了@ToString、@EqualsAndHashCode、@Getter、@Setter和@RequiredArgsConstrutor
这些注解;
@AllArgsConstructor : 加在类上,可以生成含实体类全参数的构造方法;
@NoArgsConstructor : 加在类上,可以生成无参构造方法
@RequiredArgsConstructor:加在类上,配合@NonNull注解使用,生成指定参数的构造方法。比如在age属性前面加@NonNull注解,则User生成需要age参数的构造方法;
@Getter:加在类上,可以生成实体类所有属性的getter方法;
@Setter:加在类上,可以生成实体类所有属性的setter方法;
@ToString:加在类上,调用toString()方法,可以输出实体类中所有属性的值。