筛选对象
huiche支持2种筛选对象
基于注解或规则的筛选对象
需要实现org.huiche.core.support.Searchable接口(仅用作标记,无需要实现的方法)
该方式允许用户自行定义javabean或record类(推荐) 来承载数据,最终解析生成条件, 支持2种规则,可以各选其一或混用皆可
- 使用
org.huiche.core.annotation.Search来标记操作符,属性名当作字段名(基于命名策略转换) - 使用属性名后缀来标记操作符,如
age_LT,除去后缀的部分,当作字段名(基于命名策略转换),支持的后缀可以参见org.huiche.core.support.Operator枚举
public class UserSearch implements Searchable{
@Search(operator=Operator.LT)
private Integer age;
private Integer age_GTE;
// getter/setter
}如果该bean的值是 age=25,age_GTE=20,则会生成age >= 20 AND age < 25的条件
说明
- 如果不使用
@Search也不添加后缀,默认String类型数据是包含CONTAINS(LIKE '%str%'),其他类型数据是相等(=) - 如果使用
@Search标注了operator,则会优先使用其设置的操作符
@Search指定比较操作符
public record ArtistSearch(Long id,@Search(operator=Operator.EQ) String title,@Search(operator=Operator.BETWEEN) List<Long> createTime){}比如上面ArtistSearch这个筛选对象, 如果对应属性有值(非null,非空字符,非空集合/数组),则会生成对应条件
比如这个如果传递参数为id=1,title='张三',createTime=[1767196800000,1782835200000],实际生成的查询条件为
id = 1 AND title = '张三' AND create_time BETWEEN 1767196800000 AND 1782835200000以上为最终SQL,实际因为使用PreparedStatement,生成的是带有?的SQL,并生成对应params
你可能注意到,以上生成的column都不带有表名,如果用于多表关联查询,尤其存在同名column时,就会冲突了,这时候就需要到@Search的entity或table属性
后缀指定操作符
使用属性名后缀来标记操作符,如age_LT,除去后缀的部分,当作字段名(基于命名策略转换),支持的后缀可以参见org.huiche.core.support.Operator枚举
注意
- 此方式,前端传值的属性即为带有后缀的属性名, 实际使用非常方便,但如果觉得不够优雅,请使用
@Search方式 - 某些特殊后缀依然会有类型要求, 比如
_IN,需要其值为List或Array或,分隔的字符串(如果需比较内容本身含,则无法使用),具体参加筛选对象操作符
指定entity或者table
此时生成的SQL就会自动携带其表名,变为table.column形式,注意两个不可同时指定,一般建议使用entity 只有当特殊情况,如有别名时,才使用table
指定field
有时候同一字段也需要多个查询条件,但受限于javabean/record, 不允许属性重名,这时候可以根据需要,自行命名各个条件的属性名,但是指定@Search的field属性 比如以上例子中,createTime可以改为2个属性,最终生成create_time >= ? AND create_time <= ?
public record ArtistSearch(@Search(operator=Operator.GTE,field="createTime") Long createTimeMin,@Search(operator=Operator.LTE,field="createTime") Long createTimeMax){}指定expression
有些时候被比较的可能不是列,而是经过一些运算的SQL表达式等,可以使用@Search(expression='') 来定义自定义的表达式,比如UPPER(name),如果operator=Operator.EQ 生成的SQL为
UPPER(name) = xxx使用expression 时 会直接忽略entity,table,field,直接作为静态表达式,需用户自行确保数据库兼容
忽略某些属性
有时候某个属性的筛选可能及其复杂,@Search无法满足,此时可指定operator=Operator.IGNORED, 此时该属性便会跳过系统的自动解析条件,需要你在最终sql执行前,自行读取值,转换并添加条件
public record ArtistSearch(Long id,@Search(operator=Operator.EQ) String title,@Search(operator=Operator.IGNORED) String keyword){}此时,无论对应属性是否有值,是否非空,都会跳过此字段,不会解析条件,需要你自行读取处理
作用于查询
dao的查询类方法,大部分方法都支持直接传递search对象, 或者是Consumer<Select>中,自行where(search),或者是调用Sql.parseSearch(search)转换为List<Condition>后传参
public void helloword(ArtistSearch search){
// 直接传递给方法
dao.list(search);
// 通过Consumer自行传递到where
dao.list(select->select.where(search));
// 通过Sql.parseSearch解析然后传递
List<Condition> conditions = Sql.parseSearch(search);
dao.list(conditions);
dao.list(select->select.where(conditions));
// 如果存在operator=Operator.IGNORED的值
// 您需要自行读取search里面对应的属性的值,自行转换为条件,传递给查询方法
dao.list(select->select
// 传递默认search解析的对象
.where(search)
// 自行传递解析search忽略的属性的对象
// Sql.keyword是内置一个工具类方法
// 该方法先判断传入的对象是否有效(非null,非空字符,非空集合数组等)
// 如果有效,与提供的多个列进行包含匹配生成条件
// 如果无效返回NULL(不影响语句,where传null会忽略)
.where(Sql.keyword(search.keyword(),Artist::name,Artist::stageName,Artist::bio))
);
}进一步了解筛选对象操作符
基于接口的筛选对象
该方式,需要你自行实现条件拼装,需要实现org.huiche.ast.support.Search(注意不是@Search),然后自行实现其conditions方法
编写自定义的基于接口的筛选对象
public record ArtistSearch(Long id,String name,String keyword) implements Search{
@Override
public List<Condition> conditions() {
return Arrays.asList(
Sql.condition(id, QArtist.ARTIST.id::eq),
Sql.condition(name, QArtist.ARTIST.name::contains),
Sql.keyword(keyword, QArtist.ARTIST.name, QArtist.ARTIST.stageName, QArtist.ARTIST.bio)
);
}
}说明
作用于查询
public void helloword(ArtistSearch search){
// 直接传递给方法
dao.list(search);
// 通过Consumer自行传递到where
dao.list(select->select.where(search));
// 获取条件再传递
List<Condition> conditions = search.conditions();
dao.list(conditions);
dao.list(select->select.where(conditions));
}有时候dao的方法可能无法满足你的查询需求,点击下一页了解自定义查询