9.7 KiB
9.7 KiB
Redkale FilterNode 使用易错点
创建时间:2026-02-03 基于:flux-api 项目实际代码
❌ 常见错误
1. LIKE 查询错误
错误写法:
// ❌ 错误:使用静态方法
node.and(PartnerFormRecord::getRealname, FilterNode.like(keyword));
正确写法:
// ✅ 正确:使用实例方法
node.like(PartnerFormRecord::getRealname, keyword);
2. 比较查询错误
错误写法:
// ❌ 错误:方法名拼写错误
node.and(PartnerFormRecord::getCreatedtime, FilterNode.greateEqual(starttime));
node.and(PartnerFormRecord::getCreatedtime, FilterNode.lessEqual(endtime));
正确写法:
// ✅ 正确:使用简短的方法名
node.ge(PartnerFormRecord::getCreatedtime, starttime);
node.le(PartnerFormRecord::getCreatedtime, endtime);
参考方法:
ge()- Greater or Equal(>=)le()- Less or Equal(<=)gt()- Greater Than(>)lt()- Less Than(<)
3. OR 条件错误
错误写法:
// ❌ 错误:在 and() 中混用 FilterNode 静态方法
node.and(
FilterNode.or(
PartnerFormRecord::getRealname, FilterNode.like(keyword),
PartnerFormRecord::getMobile, FilterNode.like(keyword)
)
);
正确写法:
// ✅ 正确:创建独立 OR 节点,链式调用
FilterNode orNode = new FilterNode();
orNode.or(PartnerFormRecord::getRealname, FilterNode.like(keyword))
.or(PartnerFormRecord::getMobile, FilterNode.like(keyword))
.or(PartnerFormRecord::getIdcard, FilterNode.like(keyword));
node.and(orNode);
4. 等值条件冗余
错误写法:
// ❌ 冗余:等值条件不需要特殊方法
node.and(PartnerFormRecord::getStatus, FilterNode.eq(1));
正确写法:
// ✅ 简洁:直接传值
node.and(PartnerFormRecord::getStatus, 1);
5. NOT 条件错误
错误写法:
// ❌ 错误:使用不存在的 notLike 方法
node.notLike(PartnerFormRecord::getStatus, 3);
正确写法:
// ✅ 正确:使用 notEq
node.notEq(PartnerFormRecord::getStatus, 3);
✅ 正确的模式
基础查询条件
FilterNode node = new FilterNode();
// 固定条件
node.and(PartnerFormRecord::getDraftstatus, (short) 0);
// 可选条件
if (bean.getKeyword() != null && !bean.getKeyword().isEmpty()) {
node.like(PartnerFormRecord::getRealname, bean.getKeyword());
}
// 范围查询
if (bean.getStarttime() > 0) {
node.ge(PartnerFormRecord::getCreatedtime, bean.getStarttime());
}
if (bean.getEndtime() > 0) {
node.le(PartnerFormRecord::getCreatedtime, bean.getEndtime());
}
// 不等于
node.notEq(PartnerFormRecord::getStatus, (short) 3);
OR 条件组合
// 关键词:姓名 OR 电话 OR 身份证
if (bean.getKeyword() != null && !bean.getKeyword().isEmpty()) {
FilterNode orNode = new FilterNode();
orNode.or(PartnerFormRecord::getRealname, FilterNode.like(bean.getKeyword()))
.or(PartnerFormRecord::getMobile, FilterNode.like(bean.getKeyword()))
.or(PartnerFormRecord::getIdcard, FilterNode.like(bean.getKeyword()));
node.and(orNode);
}
IN 条件
// IN 查询
FilterNode node = new FilterNode();
node.in(PartnerFormRecord::getFormdataid, formIds.toArray());
List<PartnerFormRecord> list = dataSource.queryList(PartnerFormRecord.class, node);
📋 FilterNode 方法速查表
| 方法 | 说明 | 示例 |
|---|---|---|
and() |
AND 等值条件 | node.and(Entity::getField, value) |
like() |
LIKE 模糊查询 | node.like(Entity::getField, "%keyword%") |
ge() |
>= 大于等于 | node.ge(Entity::getTime, timestamp) |
le() |
<= 小于等于 | node.le(Entity::getTime, timestamp) |
gt() |
> 大于 | node.gt(Entity::getField, value) |
lt() |
< 小于 | node.lt(Entity::getField, value) |
notEq() |
!= 不等于 | node.notEq(Entity::getStatus, 3) |
in() |
IN 查询 | node.in(Entity::getId, ids.toArray()) |
or() |
OR 条件 | 需创建独立 FilterNode |
🔍 完整示例参考
PartnerFormService.java
@RestMapping(name = "list", comment = "分页查询表单记录")
public RetResult<Sheet<PartnerFormRecord>> list(FormRecordFilterBean bean, Flipper flipper) {
FilterNode node = new FilterNode();
node.notEq(PartnerFormRecord::getStatus, STATUS_DELETED);
if (!Utils.isEmpty(bean.getRealname())) {
node.like(PartnerFormRecord::getRealname, bean.getRealname());
}
if (bean.getDraftstatus() >= 0) {
node.and(PartnerFormRecord::getDraftstatus, bean.getDraftstatus());
}
if (bean.getStarttime() > 0) {
node.ge(PartnerFormRecord::getCreatedtime, bean.getStarttime());
}
if (bean.getEndtime() > 0) {
node.le(PartnerFormRecord::getCreatedtime, bean.getEndtime());
}
Sheet<PartnerFormRecord> sheet = dataSource.querySheet(PartnerFormRecord.class, flipper, node);
return render(sheet);
}
PartnerCustomerService.java
@RestMapping(name = "list", comment = "分页查询客户列表")
public RetResult<Sheet<PartnerCustomer>> list(PartnerCustomerFilterBean bean, Flipper flipper) {
FilterNode node = new FilterNode();
node.notEq(PartnerCustomer::getStatus, (short) 3);
if (!Utils.isEmpty(bean.getMobile())) {
node.and(PartnerCustomer::getMobile, bean.getMobile());
}
if (bean.getStatus() > 0) {
node.and(PartnerCustomer::getStatus, bean.getStatus());
}
if (bean.getStarttime() > 0) {
node.ge(PartnerCustomer::getCreatedtime, bean.getStarttime());
}
if (bean.getEndtime() > 0) {
node.le(PartnerCustomer::getCreatedtime, bean.getEndtime());
}
Sheet<PartnerCustomer> sheet = dataSource.querySheet(PartnerCustomer.class, flipper, node);
return render(sheet);
}
⚠️ 注意事项
- 方法调用方式:所有条件方法都是
FilterNode实例的方法,不是静态方法 - 方法命名:
ge/le而非greateEqual/lessEqual - OR 条件:必须创建独立的
FilterNode对象进行链式调用 - 值比较:等值条件直接传值,不需要
FilterNode.eq() - LIKE 参数:通常需要在参数中自行添加
%通配符
📚 参考代码位置
flux-api/src/main/java/cn/casehub/partner/PartnerFormService.javaflux-api/src/main/java/cn/casehub/partner/PartnerCustomerService.javaflux-api/src/main/java/cn/casehub/partner/PartnerVisitService.java
Redkale JSON 使用要点
更新时间:2026-03-03 背景:速贷接口接入时错误使用
@JsonProperty(Jackson 注解),Redkale 不支持
❌ 常见错误
1. 使用 Jackson 注解
错误写法:
// ❌ 错误:Redkale 不支持 Jackson 注解
import com.fasterxml.jackson.annotation.JsonProperty;
@JsonProperty("mobile_md5")
private String mobileMd5;
正确方案:使用 Redkale 的 @ConvertColumn(name = "xxx") 进行字段重命名:
// ✅ 正确:使用 @ConvertColumn 重命名
import org.redkale.convert.ConvertColumn;
@ConvertColumn(name = "mobile_md5")
private String mobileMd5; // Java驼峰,JSON下划线
✅ JsonConvert 使用方式
序列化(对象 → JSON)
// 方式1:实例方法
JsonConvert convert = JsonConvert.root();
String json = convert.convertTo(object);
// 方式2:静态调用
String json = JsonConvert.root().convertTo(object);
反序列化(JSON → 对象)
// 单个对象
User user = JsonConvert.root().convertFrom(User.class, json);
// 泛型集合
List<User> users = JsonConvert.root().convertFrom(
new TypeToken<List<User>>() {}.getType(),
json
);
// Map(用于解析不确定结构的JSON)
Map<String, Object> map = JsonConvert.root().convertFrom(Map.class, json);
📋 字段映射规则
| Java 字段名 | JSON 字段名 | 说明 |
|---|---|---|
mobileMd5 |
mobileMd5 |
默认:驼峰 → 驼峰 |
mobile_md5 |
mobile_md5 |
默认:下划线 → 下划线 |
mobileMd5 + @ConvertColumn(name="mobile_md5") |
mobile_md5 |
✅ 重命名 |
mobileMd5 + @ConvertColumn(ignore=true) |
- | 忽略字段 |
结论:使用 @ConvertColumn(name = "xxx") 可实现字段重命名。
🔧 跨命名风格转换方案
当第三方接口使用下划线,内部使用驼峰时:
方案1:@ConvertColumn + Utils.copy(推荐)
// 速贷请求Bean(Java驼峰,JSON下划线)
public class SuDaiRequest {
@ConvertColumn(name = "mobile_md5")
private String mobileMd5;
@ConvertColumn(name = "city_id")
private String cityId;
}
// 内部Bean(驼峰)
public class CollideBean {
private String mobileMd5;
private String cityId;
}
// 转换器 - 使用 Utils.copy
public class Converter {
public static CollideBean toBean(SuDaiRequest req) {
return Utils.copy(new CollideBean(), req); // 一行搞定
}
}
方案2:手动映射(不推荐)
// 速贷请求Bean(下划线)
public class SuDaiRequest {
private String mobile_md5;
private String city_id;
}
// 转换器 - 手动映射
public class Converter {
public static CollideBean toBean(SuDaiRequest req) {
CollideBean bean = new CollideBean();
bean.setMobileMd5(req.getMobile_md5()); // 手动映射
bean.setCityId(req.getCity_id());
return bean;
}
}
⚠️ 注意事项
- 使用 @ConvertColumn:Redkale 的字段重命名注解,不是 Jackson 的 @JsonProperty
- @ConvertColumn 用法:
@ConvertColumn(name = "xxx")- 重命名JSON字段@ConvertColumn(ignore = true)- 忽略字段
- 配合 Utils.copy:重命名后,Java字段名一致,可用
Utils.copy简化转换