为自然语言与 vibe coding 而生的轻量 Java ORM
一个轻量级的 Java ORM 库,提供了一组语法可以将查询字符串直接转换为 SQL 查询。它的接口是为自然语言而生的:查询条件就是「字段|函数|操作符=值」这样的短字符串,与人类描述需求的语序几乎一一对应,因此也非常适合作为 AI / LLM 生成代码(vibe coding)的数据层目标库。
- 🔄 将查询字符串自动转换为 SQL 查询
- 🔍 支持丰富的查询操作符和函数
- 🗣️ 自然语言友好:查询 DSL 即字符串,LLM 无需理解复杂 builder API 即可准确生成
- 🤖 Vibe coding 适配:统一的方法签名 + 约定式字段映射,AI 一次对话即可完成数据访问层
- 📦 易于集成到现有项目中
- ⚡ 高性能的数据访问层
- 🛠️ 灵活的扩展机制
传统 ORM 让 LLM 写查询时,需要它精确记忆大量 builder API、类型和链接调用;任何一处拼错都会编译失败。Filaments 把查询收敛成一种高度规律、可自然表达的字符串语法:
-
需求到查询几乎零翻译成本 "查询年龄大于 18 的北京用户,按注册时间倒序" 直接映射为:
filaments.pages(db, new HashMap<>() {{ put("age|gt", 18); put("city", "北京"); put("od", "-create_time"); }});
字段|操作符=值与中文/英文的描述语序同构(字段→条件→值),LLM 最容易学会的就是这种模式化短字符串,出错率显著低于链式 API。 -
参数是纯数据(Map / String),不是代码 查询条件可以由 LLM 以 JSON 形式输出再直接传入,天然适合 Function Calling / Tool 参数场景,也便于服务端做校验与回放。复杂逻辑树用
lg表达式(如!(a=1,b=2))描述,且提供toTreeString()树形打印,AI 生成后可视化自检。 -
强约定,弱配置 驼峰字段自动转下划线列名、JSON 列自动序列化、
p/pc/pg分页、rt指定返回字段——LLM 不需要生成任何映射配置或样板代码,命名约定本身即是"提示词"。 -
接口面极小,一次对话即可上手 核心入口只有
create / updateByIds / deleteByIds / get / pages / getByIds / aggregation几个方法,第一个参数统一是DSLContext。AI 只需少量示例(few-shot)即可覆盖整个库的用法,生成的代码风格高度一致、可预测。 -
安全边界清晰 所有值走占位符绑定,注入面收敛在字段名/函数白名单内,LLM 生成的查询不会引入拼接式 SQL 注入风险,适合作为"让 AI 直接操作数据查询"的落地层。
确保你的项目使用 Gradle 或 Maven 构建,然后添加依赖:
dependencies {
implementation 'io.github.karboom:filaments-java:2.0.2'
}<dependency>
<groupId>io.github.karboom</groupId>
<artifactId>filaments-java</artifactId>
<version>2.0.2</version>
</dependency>// 创建 Filaments 实例
var userFilament = new Filaments<>(User.class);
// 使用查询字符串进行查询
var users = userFilament.get(db, new HashMap<>() {{
put("age|in", List.of(22, 23));
}});
// 分页查询
var page = userFilament.pages(db, new HashMap(){{
put("name", "x");
}});| 字段名称 | 功能 | 默认值 | 查询字符串 | 对应SQL |
|---|---|---|---|---|
| rt | 指定返回字段 | * | ?rt=name,age | select `name`, `age` |
| p | 指定当前页码 | 1 | ?p=3 | limit 20 offset 40 |
| pc | 指定页内行数 | 20 | ?pc=18 | limit 18 offset 0 |
| od | 指定排序规则 | Null | ?id,-height | order by `id` asc, `height` desc |
| pg | 是否需要计算分页(仅分页函数生效) | 0 | ?pg=1 | limit ? offset ? |
字段名|函数(参数)...|操作符=数值
| 查询字符串 | 对应SQL |
|---|---|
| ?type=dog | where `type` = 'dog' |
| ?type|in=dog,cat | where `type` in ( 'dog', 'cat') |
| ?type|substr(1,2)|in=dog,cat | where substr(`type`, 1, 2) in ( 'dog', 'cat') |
| ?type|lower|substr(1,2)|in=dog,cat | where substr(lower(`type`), 1, 2) in ( 'dog', 'cat') |
| ?data.type=dog | where `data`->'$.type' = 'dog' |
| ?data[0].type=cat | where `data`->'$[0].type' = 'cat' |
| ?data[0]=dog | where `data`->'$[0]' = 'dog' |
| 查询字符串 | 别名 | 对应SQL |
|---|---|---|
| ?id|gt=1 | where `id` > 1 |
|
| ?id|ge=1 | where `id` >= 1 |
|
| ?id|lt=1 | where `id` < 1 |
|
| ?id|le=1 | where `id` <= 1 |
|
| ?id|in=1 | where `id` in (1) |
|
| ?id|not_in=1 | nin | where `id` not in (1) |
| ?id|between=1,2 | bt | where `id` between 1 and 2 |
| ?id|not_between=1,2 | nbt | where `id` not between 1 and 2 |
| ?id|like=k% | lk | where `id` like 'k%' |
| ?id|not_like=k% | nlk | where `id` not like 'k%' |
| ?id|is_null=1 | nl | where `id` is null |
| ?id|is_not_null=1 | nnl | where `id` is not null |
对于复杂的查询需求,可以通过 sub 参数传入子查询:
var subQuery = dsl.selectQuery();
var users = userFilament.get(db, new HashMap<>() {{
put("role", "admin");
}}, subQuery);继承 Filaments 类,扩展自定义方法:
public class UserFilaments extends Filaments<User> {
public UserFilaments() {
super(User.class);
}
public List<Record> getByOrgId(DSLContext db, Long orgId) {
return db.raw();
}
}- 在数据库中编写视图
- 通过
sub参数传入构造的子查询 - 继承
Filaments类,扩展自定义方法,通过db.raw()直接编写语句
- 根据业务需求灵活选择数据库连接(主库或从库)
- 灵活选择事务上下文
欢迎提交 Issue 和 Pull Request!
Licensed under the Apache License, Version 2.0.