SkillAgentSearch skills...

FastSQL

Database rapid development framework for Java(数据库快速开发框架).

Install / Use

/learn @fast-sql/FastSQL
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

轻量级数据库访问框架FastSQL

Maven central License

logo

目录

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")生成 = 1eq("'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

View on GitHub
GitHub Stars132
CategoryDevelopment
Updated4d ago
Forks29

Languages

Java

Security Score

100/100

Audited on Mar 24, 2026

No findings