# API 规范
# Query 参数
在数据访问和生成的CRUD查询接口中,我们会接触到Queryable或Query/QueryBase(Queryable的实现类)参数,这里统称为Query参数,该参数存储了生成查询SQL中所需要的所有基本属性,如SELECT内容、WHERE内容等。Fly制定了一系列规范,按照约定的语法编写表达式,可实现基本的数据查询需求。
- 数据访问查询
Query query = Query.filters(Filters.parse("name eq 1")).build();
// SELECT id, name FROM news WHERE name = '1'
dao.createQuery(NewsEntity.class).execute(query);
dao.createQuery(NewsEntity.class).queryable(query).list();
CRUD查询接口
简单示例,filters参数可以在查询中进行数据过滤(WHERE),Controller实现CRUD的查询接口FlexibleCrudQuery:
@RestController
@RequestMapping("/news")
@Crud(entityClass = NewsEntity.class)
public class NewsEntityController implements FlexibleCrudQuery {}
请求内容:
GET /news?filters=name eq '1 2'
注意若值含有空格,需要用'单引号括住。最终生成的查询SQL为:
SELECT id, name FROM news WHERE name = '1 2'
# 字段选择
属性参数名为select,用于选择只返回需要的字段,减少数据传输大小。
- 多个字段使用英文逗号分隔;
- 查询字段&表达式指定别名,使用空格连接别名。
GET /news?select=id,name n
# 数据过滤
属性参数名为filters,传入表达式,通过特定的语法实现WHERE过滤。
可使用的查询操作符:
| 操作符 | SQL | 说明 | 示例 |
|---|---|---|---|
| eq | = | 等于 | filters=name eq Tom |
| lt | < | 小于 | filters=age lt 20 |
| le | <= | 小于或等于 | filters=age le 20 |
| gt | > | 大于 | filters=age gt 20 |
| ge | >= | 大于或等于 | filters=age ge 20 |
| ne | != | 不等于 | filters=age ne 20 |
| like | like | 模糊查询 | filters=name like T% |
| in | in | 在指定的值内查询 | filters=name in (n1,n2) |
| not in | not in | 排除指定的值查询(Since 0.6.1-SNAPSHOT) | filters=name not in (n1,n2) |
| is | is | 相当于sql关键字is | filters=name is null |
| not | is not | 相当于sql关键字is not | filters=name not null |
| and | and | 表示多条件间的且关系 | filters=name like T% and age lt 20 |
| or | or | 表示多条件间的或关系 | filters=name like T% or age lt 20 |
| () | () | 表达式组,可以用来改变表达式的优先级关系 | filters=name like T% and ((age lt 20) or (name like %y)) |
注意参数、操作符和值之间的空格。
# 数据排序
属性参数名为orderBy,排序表达式,多个排序项用英文逗号分隔:
GET /news?orderBy=createdAt desc,name asc
# 关联查询
属性参数名为joins,关联表达式,通过特定的语法实现关联查询:
joins={relation} {alias}[,{relation} {alias}]
关联查询后的关系别名,可以应用于select、filters等参数中,示例:
Member成员实体的userId字段关联User用户实体。
@Entity
public class User {
@Id
protected String id;
@Column
protected String name;
// get/set
}
@Entity
public class Member {
@Id
protected String id;
@ManyToOne(relation = "user", targetEntity = User.class)
protected String userId;
// get/set
}
Member成员实体创建查询接口:
@RestController
@RequestMapping("/memebr")
@Crud(entityClass = Member.class)
public class NewsEntityController implements FlexibleCrudQuery {}
根据成员的用户名称过滤并返回用户名称,请求为:
GET /member?select=u.name userName&filters=u.name eq 'system'&joins=user u
# 展开查询
属性参数名为expand,用于在一次请求中查询返回某实体的记录以及关联实体的记录。多个关系用英文逗号分隔:
GET /news?expand={relation}[,{relation}]
展开查询内容保存到与关系名同名的返回属性中,不同类型关系返回数据结构如下:
- 多对一关系
{
"id": "...",
"name": "...",
"{relation}": {
"id": "..."
}
}
- 一对多关系
{
"id": "...",
"name": "...",
"{relation}": [
{
"id": "..."
}
]
}
# 指定展开查询的字段
如展开查询多对一关系user,关系实体有id、name、createdAt等字段,在展开查询中只需要返回name:
GET /news?expand=user(name)
请求返回内容:
{
"id": "...",
"name": "...",
"user": {
"name": "..."
}
}
# 展开查询中设置参数
Since 0.8.1
如展开查询多对一关系user,关系实体有id、name、createdAt等字段,展开查询只需要返回name,且添加filters过滤或orderby排序:
GET /news?expand=user(select:name)
GET /news?expand=user(filters:name eq demo)
GET /news?expand=user(orderby:name desc)
组合使用:
GET /news?expand=user(select:id,name,orderby:name desc)
# 数据分页
分页参数组合有:
- 分页
| 参数 | 类型 | 作用 |
|---|---|---|
page | Integer | 指定查询页码,从1开始 |
page_size | Integer | 指定查询页大小 |
GET /news?page=1&page_size=10
- 查询行&偏移量
| 参数 | 类型 | 作用 |
|---|---|---|
limit | Integer | 指定查询行,类似SQL中的limit |
offset | Integer | 查询偏移量,表示偏移几行开始返回,与limit配合使用实现分页。从0开始 |
GET /news?limit=10
GET /news?limit=10&offset=20
# 异常处理
内置了几个常见场景的响应异常,在API执行中直接抛出该异常,返回的状态码为:
| 异常 | 状态码 |
|---|---|
| BadRequestException | 400 |
| ConflictException | 409 |
| ForbiddenException | 403 |
| NotFoundException | 404 |
| NotImplementedException | 501 |
异常依据Spring规范定义,使用了org.springframework.http.HttpStatus中的状态码,异常详细描述可以见https://tools.ietf.org/html/rfc7231 (opens new window)。