FastSQL
Database rapid development framework for Java(数据库快速开发框架).
Install / Use
/learn @fast-sql/FastSQLREADME
轻量级数据库访问框架FastSQL

目录
1 简介
FastSQL一个基于spring-jdbc的简单ORM框架,它支持sql构建、sql执行、命名参数绑定、查询结果自动映射和通用DAO。结合了Hibernate/JPA快速开发和Mybatis高效执行的优点。
FastSQL可以完全满足你控制欲,可以用Java代码清晰又方便地写出sql语句并执行。
FastSQL完全可用于生产环境,相比Mybatis,使用简单,开发效率高。
2 入门
2.1 安装
如果使用 Maven 来构建项目,则需将下面的 dependency 代码置于 pom.xml 文件中:
<dependency>
<groupId>top.fastsql</groupId>
<artifactId>fastsql</artifactId>
<version>1.3.0</version>
</dependency>
如果使用 Gradle 来构建项目,则需将下面的代码置于 build.gradle 文件的 dependencies 代码块中:
compile 'top.fastsql:fastsql:1.3.0'
2.2 构建 SQLFactory
你可以直接从 Java 程序构建一个 SQLFactory ,如果使用SQL的执行功能,至少需要设置 DataSource 。
//新建一个DataSource(这里使用了spring-jdbc的SimpleDriverDataSource)
//也可以使用支持连接池的各种DataSource,如DruidDataSource等
DataSource dataSource = new SimpleDriverDataSource(<...省略参数...>);
SQLFactory sqlFactory = new SQLFactory();
sqlFactory.setDataSource(dataSource);
2.3 从 SQLFactory 中获取 SQL
既然有了 SQLFactory ,我们就可以从中获得 SQL 的实例了。SQL类完全包含了面向数据库执行 sql 命令所需的所有方法。 你可以通过 SQL 实例来构建并直接执行 SQL 语句。例如:
SQL sql = sqlFactory.sql();
Student student = sql.SELECT("*").FROM("student").WHERE("id=101").queryOne(Student.class);
2.4 作用域(Scope)和生命周期
SQLFactory
SQLFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由对它进行清除或重建。 使用 SQLFactory 的最佳实践是在应用运行期间不要重复创建多次,多次重建 SQLFactory 被视为一种代码“坏味道(bad smell)”。 因此 SQLFactory 的最佳作用域是应用的作用域。有很多方法可以做到,最简单的就是使用单例模式或者静态单例模式 (如果在Spring环境中,利用Spring容器的功能,你完全可以把它设置为一个单例bean)。
SQL
SQL 实例是有状态的 ,不是线程安全的,是不能被共享的。即使在同一个线程中每执行sql语句一次,都需要重新构建一个 SQL 实例。 绝对不能将 SQL 实例的引用放在一个类的静态域,甚至一个类的实例变量也不行。
3 SQLFactory 配置
新建SQLFactory
SQLFactory sqlFactory = new SQLFactory();
指定DataSource
//新建任意类型一个DataSource,如SimpleDriverDataSource(Spring内部提供的)
// 或者其他支持连接池的DataSource
DataSource dataSource = ... ;
//设置数据源
sqlFactory.setDataSource(dataSource);
设置数据源类型
sqlFactory.setDataSourceType(DataSourceType.POSTGRESQL);//默认
//支持 DataSourceType.POSTGRESQL、 DataSourceType.MY_SQL、DataSourceType.ORACLE
其他设置
sqlFactory.setQueryTimeout(5000);//设置最大超时时间
sqlFactory.setMaxRows(100);//查询最大行数
4 使用SQL类构建sql语句
Java程序员面对的最痛苦的事情之一就是在Java代码中嵌入SQL语句。SQL类可以简化你构建sql语句的过程。
4.1 基本查询
SELECT方法可以传入一个可变参数,以便选择多列。(FastSQL中建议SQL关键字全部采用大写)
sqlFactory.sql().SELECT("name", "age").FROM("student").WHERE("age>10").build();
//==> SELECT name,age FROM student WHERE age>10
sqlFactory.sql().SELECT("name", "age").FROM("student").WHERE("name='小红'").build();
//==> SELECT name,age FROM student WHERE name='小红'
WHERE()关键字生成WHERE 1=1语句,动态sql构建如下
SQL sql = sqlFactory.sql().SELECT("name", "age").FROM("student").WHERE();
if (true){
sql.AND("age > 10");
}
if (false){
sql.AND("age < 8");
}
//生成sql=>SELECT name,age FROM student WHERE 1 = 1 AND age > 10
4.2 使用操作符方法
FastSQL提供了一些操作符方便SQL的构建,比如:
sqlFactory.sql()
.SELECT("name", "age")
.FROM("student")
.WHERE("age").lt("10")
.AND("name").eq("'小明'")
.build();
//生成sql=> SELECT name,age FROM student WHERE age < 10 AND name = '小明'
如下:
| 方法 | 说明 | | :--------------- | :---------------------------------------------------- | | eq(String) | 生成 = ,并追加参数(equal的缩写) | | gt(String) | 生成 > ,并追加参数(是greater than的缩写) | | gtEq(String) | 生成 >= ,并追加参数(是greater than or equal的缩写) | | lt(String) | 生成 < ,并追加参数(是less than的缩写 ) | | ltEq(String) | 生成 <= ,并追加参数(是less than or equal的缩写) | | nEq(String) | 生成 != ,并追加参数(是not equal的缩写 ) | | LIKE(String) | 生成 LIKE ,并追加参数, | | NOT_LIKE(String) | 生成 NOT LIKE ,并追加参数 | | IS_NULL() | 生成 IS NULL | | IS_NOT_NULL() | 生成 IS NOT NULL | | eq() | 生成 = | | gt() | 生成 > | | gtEq() | 生成 >= | | lt() | 生成 < | | ltEq() | 生成 <= | | nEq() | 生成 != | | LIKE() | 生成 LIKE | | NOT_LIKE() | 生成 NOT LIKE |
byType(Object)
这些方法仅仅是字符串连接:eq("1")生成 = 1 ,eq("'1'")会生成 = '1'。byType(Object)方法可以根据类型生成你想要的sql字符串
sqlFactory.sql()
.SELECT("name", "age")
.FROM("student")
.WHERE("age").lt().byType(10)
.AND("name").eq().byType("小明")
.build();
//==>SELECT name,age FROM student WHERE age < 10 AND name = '小明'
| 方法 | 说明 | | :--------------- | :-------------------------------------------------------------- | | byType(Object) | 根据类型生成相应字符串 ,如 byType(1)生成1 ,byType("1")生成'1' | | eqByType(Object) | 使用 = 连接根据类型生成相应的字符串 |
4.3 使用连接查询/排序
查询不及格的成绩
sqlFactory.sql().SELECT("s.name","c.subject_name","c.score_value")
.FROM("score c")
.LEFT_JOIN_ON("student s", "s.id=c.student_id")
.WHERE("c.score_value<60")
.ORDER_BY("c.score_value")
.build();
/*
生成sql =>
SELECT s.name, c.subject,c.score_value
FROM score c
LEFT OUTER JOIN student s ON (s.id = c.student_id)
WHERE c.score_value < 60
ORDER BY c.score_value
*/
4.4 分组查询
查询每个学生总分数
sqlFactory.sql().SELECT("s.name", "sum(c.score_value) total_score")
.FROM("score c")
.LEFT_JOIN_ON("student s", "s.id=c.student_id")
.GROUP_BY("s.name")
.build()
/*
生成sql==>
SELECT s.name, sum(c.score_value) total_score
FROM score c
LEFT OUTER JOIN student s ON (s.id = c.student_id)
GROUP BY s.name
*/
4.5 IN语句
由于Jdbc规范不支持IN参数绑定,FastSQL提供了几种IN语句直接拼接的方式:
//1.使用字符串
sqlFactory.sql().SELECT("*")
.FROM("student")
.WHERE("name").IN("('小明','小红')")
.build();
//2.使用集合(List,Set等)
sqlFactory.sql().SELECT("*")
.FROM("student")
.WHERE("name").IN(Lists.newArrayList("小明","小红"))
.build();
//3.使用数组
sqlFactory.sql().SELECT("*")
.FROM("student")
.WHERE("name").IN(new Object[]{"小明","小红"})
.build();
//4.使用可变参数(最简洁)
sqlFactory.sql().SELECT("*")
.FROM("student")
.WHERE("name").IN_var("小明","小红")
.build();
//生成sql==> SELECT * FROM student WHERE name IN ('小明','小红')
~~4.6 使用$_$()方法进行子查询~~
~~查询大于平均分的成绩(可以使用 $_$()方法)~~
sqlFactory.sql().SELECT("*")
.FROM("score")
.WHERE("score_value >")
.$_$(
sqlFactory.sql().SELECT("avg(score_value)").FROM("score")
)
.build();
//生成sql==>
//SELECT * FROM score
//WHERE score_value > ( SELECT avg(score_value) FROM score )
~~带有IN的子查询~~
sqlFactory.sql().SELECT("*")
.FROM("score")
.WHERE()
.AND("score")
.IN().$_$(
sqlFactory.sql().SELECT("DISTINCT score_value").FROM("score")
)
.build();
//生成sql==> SELECT * FROM score WHERE 1 = 1 AND score IN (SELECT DISTINCT score_value FROM score)
注:复杂sql推荐使用字符串直接构建:
String sql="SELECT * FROM score WHERE 1 = 1 AND score IN (SELECT DISTINCT score_value FROM score)";
sqlFactory.sql().str(sql);
4.7 AND和OR结合使用
如果查询年龄大于10岁,并且名字是小明或小红
sqlFactory.sql().SELECT("*")
.FROM("student")
.WHERE("age>10")
.AND("(name='小明' OR name='小红')")//手动添加括号
.build();
//或者
sqlFactory.sql().SELECT("*")
.FROM("student")
.WHERE("age>10")
.AND().$_$("name='小明' OR name='小红'")//$_$ 生成左右括号
.build();
4.8 使用Lambda表达式简化构建动态sql
ifTrue(boolean bool, Consumer<SQL> sqlConsumer):如果第1个参数为true,则执行第二个参数(Lambda表达式)ifNotEmpty(Collection<?> collection, Consumer<SQL> sqlConsumer):如果第1个参数长度大于0,则执行第二个参数(Lambda表达式)ifPresent(Object object, Consumer<SQL> sqlConsumer):如果第1个参数存在(不等于null且不为""),则执行第二个参数(Lambda表达式)ifEquals(Object object1, Object object2, Consumer<SQL> sQLConsumer):如果前两个参数相等,则执行lambda表达式
sqlFactory.sql()
.SELECT("student")
.WHERE("id=:id")
.ifTrue(true, sql -> thisBuilder.AND("name=:name"))
.ifNotEmpty(names, sql -> {
System.out.println("ifNotEmpty?");
thisBuilder.AND("name").IN(Lists.newArrayList("小明", "小红"));
})
.ifPresent("",sql -> {
System.out.println("ifPresent?");
//...处理其他流程语句...
})
.build();
输出:
ifNotEmpty?
SELECT student WHERE id=:id AND name=:name AND name IN ('小明','小红')
4.9 分页功能
使用原生关键字进行分页
sqlFactory.sql().SELECT("*").FROM("student").LIMIT(10).build();
sqlFactory.sql().SELECT("*").FROM("student").LIMIT(5, 10).build(); //mysql中的写法
sqlFactory.sql().SELECT("*").FROM("student").LIMIT(10).OFFSET(5).build(); //postgresql中的写法
生成如下SQL
SELECT * FROM student LIMIT 10;
SELECT * FROM student LIMIT 5,10;
SELECT * FROM student LIMIT 10 OFFSET 5;
使用 pageThis(int,int) 分页方法进行分页
//
sqlFactory.setDataSourceType(DataSourceType.POSTGRESQL); //使用枚举指定数据源类型
sqlFactory.sql().SELECT("*").FROM("student").pageThis(1,10).build();
注意:如果不指定 dataSourceTyp
Related Skills
node-connect
339.1kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
oracle
339.1kBest practices for using the oracle CLI (prompt + file bundling, engines, sessions, and file attachment patterns).
prose
339.1kOpenProse VM skill pack. Activate on any `prose` command, .prose files, or OpenProse mentions; orchestrates multi-agent workflows.
frontend-design
83.8kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
