• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

FastSQL: FastSQL一个基于spring-jdbc 的简单 ORM 框架,它支持 sql 构建、sql 执行、 ...

原作者: [db:作者] 来自: 网络 收藏 邀请

开源软件名称:

FastSQL

开源软件地址:

https://gitee.com/mirrors/FastSQL

开源软件介绍:

轻量级数据库访问框架FastSQL

Maven centralLicense

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内部提供的)//  或者其他支持连接池的DataSourceDataSource 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>10sqlFactory.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_valueFROM score cLEFT OUTER JOIN student s ON (s.id = c.student_id)WHERE c.score_value < 60ORDER 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_scoreFROM score cLEFT 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();

注意:如果不指定 dataSourceType,将会默认使用 postgresql 数据库类型进行分页;

使用 countThis() 生成获取数量语句

//countThissqlFactory.sql().SELECT("*").FROM("student").countThis().buildAndPrintSQL();

4.10 构建插入insert/修改update/删除delete语句

插入

//使用列sqlFactory.sql().INSERT_INTO("student", "id", "name", "age")                .VALUES("21", "'Lily'", "12").build();//=>INSERT INTO student (id,name,age)  VALUES (21,'Lily',12)//不使用列sqlFactory.sql().INSERT_INTO("student").VALUES("21", "'Lily'", "12").build();//=>INSERT INTO student VALUES (21,'Lily',12)

修改

SET(String...items) :SET关键字

sqlFactory.sql().UPDATE("student").SET("name = 'Jack'","age = 9").WHERE("name = 'Mike'").build();//=>  UPDATE student SET name = 'Jack',age = 9 WHERE name = 'Mike'

构建删除语句

sqlFactory.sql().DELETE_FROM("student").WHERE("id=12").build();//=>DELETE FROM student WHERE id=12

5 使用SQL类执行sql语句

5.1 创建SqlFactory

//创建任意DataSource对象(这里使用了spring自带的数据源SimpleDriverDataSource)DataSource dataSource = new SimpleDriverDataSource(                new Driver(), "jdbc:postgresql://192.168.0.226:5432/picasso_dev2?stringtype=unspecified",                "developer", "password");//创建SqlFactorySqlFactory sqlFactory = new SqlFactory();sqlFactory.setDataSource(dataSource);sqlFactory.setDataSourceType(DataSourceType.MY_SQL);

5.2 设置参数的方法

FastSQL支持多种传入命名参数的方法:

  • parameter(SqlParameterSource) 支持传入SqlParameterSource类型的参数(为了兼容spring-jdbc)。
  • beanParameter(Object)方法可以传入对象参数。
  • mapParameter(Map<String, Object>)支持传入Map类型参数。
  • mapItemsParameter(Object...)支持多个key-value形式的参数,比如mapItemsParameter("id", 12345,"name","小明")
  • beanAndMapParameter(Object, Map<String, Object>) 支持两种不同的参数组合,后一个map会覆盖前面bean中的相同名字的参数。
  • addMapParameterItem(String, Object)可以为以上几种传参方法追加参数。

注意:以上方法除了addMapParameterItem只能调用一次,调用多次会导致前面的传参被覆盖。如需追加参数,请使用addMapParameterItem

FastSQL也支持?占位符和可变参数:

  • varParameter(Object... vars) 传入可变参数,可以调用多次,用来追加参数。

示例

使用beanParameter方法支持传入一个参数bean

public class StudentDTO{    private String name;    private int age;    //省略set和get方法}
StudentDTO dto =new StudentDTO();dto.setName="小明";dto.setAge=10;sqlFactory.sql().SELECT("*")    .FROM("student")    .WHERE("name=:name")    .AND("age>:age")    .beanParameter(dto)  //设置一个DTO查询参数    .queryList(StudVO.class);

使用beanParameter方法并追加参数

Map<String,Object> param = new HashMap<>();map.put("name","李%");sqlFactory.sql()    .SELECT("*")    .FROM("student")    .WHERE("name").LIKE(":name")    .AND("age > :age")    .beanParameter(param)  //设置一个map参数    .addParameterMapItem("age",12) //追加    .queryList(Student.class);

使用varParameter方法--支持?占位符和可变参数

SQL sql = sqlFactory.sql();sql.INSERT_INTO("student", "id", "name", "age")    .VALUES("?", "?", "?")    .varParameter("123", "小明")    .varParameter(12)    .update();

5.3 查询方法

5.3.1 查询方法解析

  • T queryOne(Class<T> returnClassType)查询单行结果封装为一个对象,参数可以是可以为String/Integer/Long/Short/BigDecimal/BigInteger/Float/Double/Boolean或者任意POJO的class。
  • Map<String, Object> queryMap()查询单行结果封装为Map
  • List<T> queryList(Class<T> returnClassType)查询多行结果封装为一个对象列表
  • List<Map<String, Object>> queryMapList()查询多行结果封装为Map数组
  • List<Object[]> queryArrayList() 查询结果封装为泛型为Object数组的列表
  • ResultPage<T> queryPage(int page, int perPage, Class<T> returnClassType) 查询结果页

5.3.2 示例

StudentVO是查询视图类,包含name和age字段;StudentDTO是查询参数类,包含name字段。

//queryList可以查询列表,可以是基本类型列表或对象列表List<String> strings = sqlFactory.sql().SELECT("name")                .FROM("student")                .queryList(String.class); //这里执行查询列表并指定返回类型List<StudVO> studVOList = sqlFactory.sql().SELECT("name", "age")                            .FROM("student")                            .WHERE("name=:name")                            .beanParameter(new StudentDTO())  //设置一个DTO查询参数                            .queryList(StudVO.class);     //查询一个对象列表//queryOne可以查询一个值,可以是基本类型  或 对象String name = sqlFactory.sql().SELECT("name")                 .FROM("student")                 .WHERE("id=:id")                 .AND("name=:name")                 .mapItemsParameter("id", 12345) //可以传入多个k-v值,,还可以调用parameterMap传入Map参数,                 .addParameterMapItem("name", "Jack")// 使用addParameterMapItem追加k-v值                 .queryOne(String.class);  //这里执行查询一个对象(基本类型)并指定返回类型StudVO studVO = sqlFactory.sql().SELECT("name", "age")                   .FROM("student")                   .WHERE("name=:name")                   .beanParameter(new StudentDTO())  //设置一个DTO                   .queryOne(StudVO.class);     //查询一个对象 
                       
                    
                    

鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap