Skip to content

Commit

Permalink
完善文档
Browse files Browse the repository at this point in the history
  • Loading branch information
blinkfox committed Jan 2, 2021
1 parent 897b238 commit ec7c8a7
Show file tree
Hide file tree
Showing 16 changed files with 277 additions and 265 deletions.
13 changes: 8 additions & 5 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
# 🍑 简介
# 🍑 简介 :id=introduction

> [🔥 Fenix](https://github.com/blinkfox/fenix)(菲尼克斯)是一个为了解决复杂动态 SQL (`JPQL`) 而生的 `Spring Data JPA` 扩展库,目的是辅助开发者更方便快捷的书写复杂、动态且易于维护的 SQL,支持 `XML`、Java 链式 `API` 和动态条件注解等四种方式来书写动态 SQL。
**🏕️ 使用示例**

- [⛱️ 示例项目 (fenix-example)](https://github.com/blinkfox/fenix-example)
- [🏝️ Fenix 使用的单元测试](https://github.com/blinkfox/fenix/tree/develop/src/test/java/com/blinkfox/fenix/repository)

## 💎 特性
## 💎 特性 :id=features

- 简单、轻量级、无副作用的集成和使用,jar 包仅 `191 KB`
- 作为 JPA 的扩展和增强,兼容 Spring Data JPA 原有功能和各种特性;
Expand All @@ -18,7 +21,7 @@
- SQL 执行结果可返回任意自定义的实体对象,比使用 JPA 自身的投影方式更加简单和自然;
- 具有可扩展性,如:可自定义 `XML` 语义标签和对应的标签处理器来生成自定义逻辑的 SQL 片段和参数;

## 🎁 初衷
## 🎁 初衷 :id=original-intention

随着 [Spring Data JPA](https://spring.io/projects/spring-data-jpa) 越来越流行,极大的方便了数据的“增删改”和简单查询的场景,但是在复杂、动态查询方面就显得有些“糟糕”了,相比 `MyBatis``XML` 动态 SQL 而言,缺少了一定优雅和可维护性,而使用原生的 `Specification` 又显得过于“臃肿”。

Expand All @@ -30,10 +33,10 @@

> **💡 注**:本 `Fenix` 扩展库开发的核心思想来源于我几年前写的动态 SQL 拼接库 [Zealot](https://github.com/blinkfox/zealot)。如果你熟悉星际争霸的话,大概能理解其中的关系。
## 📝 开源许可证
## 📝 开源许可证 :id=license

`Fenix` 的 Spring Data JPA 扩展库遵守 [Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0) 许可证。

## 🙏 鸣谢
## 🙏 鸣谢 :id=thanks

感谢 [JetBrains 公司](https://www.jetbrains.com/?from=fenix) 为本开源项目提供的免费正版 Intellij IDEA 的 License 支持。
10 changes: 5 additions & 5 deletions docs/compare-mybatis.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# 🍎 与 MyBatis XML 的 SQL 写法比较
# 🍎 与 MyBatis XML 的 SQL 写法比较 :id=title

## 🌴 假设业务查询场景
## 🌴 假设业务查询场景 :id=business-scenario

下面将通过一个多条件查询**操作日志**的功能,来初步了解和比较 `MyBatis``Fenix` 在写“**多条件模糊分页**”查询时 SQL 写法的一些差异和各自的特点。

Expand All @@ -13,7 +13,7 @@
- **操作结果**:数据库字段类型为 `int` 型,只能下拉选择一个选项值来进行**等值查询**`=`);
- **操作时间**:数据库字段类型为 `datetime` 型,可以选择开始时间或者结束时间来进行**区间查询**`BETWEEN ? AND ?``>=``<=`);

## 🌼 使用 MyBatis XML 的 SQL 写法
## 🌼 使用 MyBatis XML 的 SQL 写法 :id=mybatis-xml

```xml
<?xml version="1.0" encoding="UTF-8"?>
Expand Down Expand Up @@ -71,7 +71,7 @@
</mapper>
```

## 🌺 使用 Fenix XML 的 SQL 写法
## 🌺 使用 Fenix XML 的 SQL 写法 :id=fenix-xml

```xml
<?xml version="1.0" encoding="UTF-8"?>
Expand Down Expand Up @@ -99,7 +99,7 @@
</fenixs>
```

## 🌸 比较总结
## 🌸 比较总结 :id=summary

`MyBatis``Fenix` 的 SQL 有以下几个差异点:

Expand Down
8 changes: 4 additions & 4 deletions docs/java/example.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# 🍗 总体示例
# 🍗 总体示例 :id=title

在 Fenix 中书写动态 SQL,也可以使用 Java 链式 `API` 代码来完成,使用方式和 `MyBatis` 的方式总体相似,但是 Fenix 的 Java 动态 SQL 的 `API` 更为强大,且大多数方法同 `XML` 中 SQL 语义化标签相对应。

下面直接通过示例来说明如何使用。

## 🎠 一、创建提供 SqlInfo 的方法
## 🎠 一、创建提供 SqlInfo 的方法 :id=provider-method

创建一个 `BlogSqlProvider` 类,在类中创建一个返回 `SqlInfo` 示例的方法,这里作为示例我取名为 `queryBlogsWithJava`,方法参数最好与 `BlogRepository` 接口中的查询方法保持一致,并用 `@Param` 注解来描述,方法的参数顺序可以调换,参数可以变少,但不应该增多(因为多余的参数值,也会是 `null`)。

Expand Down Expand Up @@ -51,7 +51,7 @@ public class BlogSqlProvider {
}
```

## 🎠 二、创建查询方法
## 🎠 二、创建查询方法 :id=query-method

`BlogRepository.java` 接口中添加动态查询博客信息的方法,我这里也取名为 `queryBlogsWithJava`。注意,这里也使用到了 `@QueryFenix` 注解,但是注解元素用得是 `provider``method`

Expand All @@ -76,7 +76,7 @@ List<Blog> queryBlogsWithJava(@Param("blog") Blog blog, @Param("startTime") Date
- `method`:表示 `SqlInfo` 提供类的方法名,值为方法名的字符串。**非必填**元素。如果不填写这个值,就默认视为提供的方法名就是 `repository` 接口的查询方法名。示例中它的值就是我们前面创建的 `queryBlogsWithJava` 方法。
- `countMethod()`:表示通过 Java 来拼接分页查询时查询总记录数 SQL 语句的提供类的方法名。

## 🎢 三、创建并执行单元测试
## 🎢 三、创建并执行单元测试 :id=unit-test

`BlogRepositoryTest` 单元测试类中,新增 `queryBlogsWithJava` 测试方法,代码如下:

Expand Down
106 changes: 54 additions & 52 deletions docs/java/main-method.md
Original file line number Diff line number Diff line change
@@ -1,39 +1,41 @@
## 🐫 一、无参静态方法
# 🍖 API 方法 :id=title

## 🐫 一、无参静态方法 :id=no-param-static-method

!> **💡 注意**:这里的**无参静态方法**是指拼接 SQL 时仅仅拼接文本字符串,不会添加 SQL 的命名参数,且无动态判断是否生成该段 SQL 片段的能力。作用是和待拼接的字符串自动拼接在一起,省去了 `SQL 关键字` 的书写,目的是用来提高SQL的可读性。

### 💻 1. 主要方法
### 💻 1. 主要方法 :id=main-methods

SQL中的关键字很多,`Fenix` 封装了大多数常用的关键字作为连接 SQL 字符串的方法,如上面总体示例所列出的 `select()``from()``select()` 等,在流式拼接的过程中,使得 SQL 的可读性和连贯性大大提高了。下面列出了大多数常用的关键字方法,来**用于拼接字符串文本,但不能传递 SQL 参数**

- insertInto(String text)
- values(String text)
- deleteFrom(String text)
- update(String text)
- select(String text)
- from(String text)
- and(String text)
- or(String text)
- as(String text)
- set(String text)
- innerJoin(String text)
- leftJoin(String text)
- rightJoin(String text)
- fullJoin(String text)
- on(String text)
- orderBy(String text)
- groupBy(String text)
- having(String text)
- limit(String text)
- offset(String text)
- asc()
- desc()
- union()
- unionAll()

> **以上方法主要作用**:用方法名所代表的关键字后追加空格,再拼接上 `text` 文本参数,其方法名称已经体现了具体用途和使用场景,这里不在赘述。
### 🔌 2. 使用示例
- `insertInto(String text)`
- `values(String text)`
- `deleteFrom(String text)`
- `update(String text)`
- `select(String text)`
- `from(String text)`
- `and(String text)`
- `or(String text)`
- `as(String text)`
- `set(String text)`
- `innerJoin(String text)`
- `leftJoin(String text)`
- `rightJoin(String text)`
- `fullJoin(String text)`
- `on(String text)`
- `orderBy(String text)`
- `groupBy(String text)`
- `having(String text)`
- `limit(String text)`
- `offset(String text)`
- `asc()`
- `desc()`
- `union()`
- `unionAll()`

> **🔔 以上方法主要作用**:用方法名所代表的关键字后追加空格,再拼接上 `text` 文本参数,其方法名称已经体现了具体用途和使用场景,这里不在赘述。
### 🔌 2. 使用示例 :id=static-method-demo

!> **💡 注**:下面的示例仅是为了演示相关 `API` 的使用,具体 SQL 运行时的正确性,你不用特别在意,实际业务场景中不会这样写。

Expand Down Expand Up @@ -77,11 +79,11 @@ public void testSelect() {
}
```

## 🦒 二、text
## 🦒 二、text :id=text

`text()` 系列的方法作用同 `XML` 中的 [text 标签](xml/xml-tags?id=text)比较类似,是用来任意传递拼接 SQL 字符串和参数的,主要目的是为了提高 SQL 拼接的灵活性。

### 💿 1. 主要方法
### 💿 1. 主要方法 :id=text-methods

下面是 `text()` 系列的重载方法:

Expand Down Expand Up @@ -126,11 +128,11 @@ public void testText() {
}
```

## 🐘 三、param 和 params
## 🐘 三、param 和 params :id=params

`param()``params()` 方法的作用是为了任意传递 SQL 参数的,目的也是为了提高 SQL 拼接过程中 SQL 参数的灵活性。

### 💾 1. 主要方法
### 💾 1. 主要方法 :id=params-methods

```java
// 在 SQL 的参数集合中添加命名参数,其中 key 是 JPQL 中的命名参数名称,value 是该参数对应的值.
Expand All @@ -140,13 +142,13 @@ param(String key, Object value)
params(Map<String, Object> paramMap)
```

### 📺 2. 使用示例
### 📺 2. 使用示例 :id=params-demo

关于 `param` 的使用示例可以直接参考 [text 的使用示例](java/main-method?id=text-example) 即可。

## 🐭 四、equal
## 🐭 四、equal :id=equal

### 📷 1. 方法介绍
### 📷 1. 方法介绍 :id=equal-methods

`equal` 系列是用来拼接 SQL 中等值查询的系列方法,生成如:`u.email = :email` 这样的等值查询且附带绑定参数的功能,其主要包含如下方法:

Expand Down Expand Up @@ -178,7 +180,7 @@ orEqual(String field, Object value, String name, boolean match) // v2.3.0 版本
- `value`,表示 Java 中的变量或常量值;
- `match`,表示是否生成该 SQL 片段,值为 `true` 时生成,否则不生成;

## 🐁 五、与 equal 类似的方法
## 🐁 五、与 equal 类似的方法 :id=equal-similar

`equal`(等于)类似的系列方法还有**不等于****大于****小于****大于等于****小于等于****模糊查询**,各系列分别如下:

Expand All @@ -197,9 +199,9 @@ orEqual(String field, Object value, String name, boolean match) // v2.3.0 版本

!> 以上各系列的方法和参数也同 `equal`,这里就不再赘述了。

## 🦛 六、between
## 🦛 六、between :id=between

### 🕯️ 1. 方法介绍
### 🕯️ 1. 方法介绍 :id=between-methods

`between` 系列方法是用来拼接 SQL 中区间查询的系列方法,生成如:`u.age BETWEEN :u_age_start AND :u_age_end`这样的区间查询功能,主要包含如下方法:

Expand Down Expand Up @@ -233,7 +235,7 @@ orEqual(String field, Object value, String name, boolean match) // v2.3.0 版本
- `endValue`,表示区间查询的结束值;
- `match`,表示是否生成该SQL片段,值为`true`时生成,否则不生成;

### 🔦 2. 使用示例
### 🔦 2. 使用示例 :id=between-demo

!> ****:下面的示例仅是为了集中演示 `between` 的使用,具体 SQL 运行时的正确性,你不用特别在意。

Expand Down Expand Up @@ -267,9 +269,9 @@ assertEquals(3, sqlInfo.getParams().size());

!> **💡 注意**:Fenix 中会对 `start``end` 的值做 `null` 的空检测。区间查询中如果 `start` 为空,`end` 不为空,则会退化为大于等于查询;如果 `start` 为空,`end` 不为空,则会退化为小于等于查询;如果 `start``end` 均不为空,则是区间查询;两者会均为空则不生产此条 SQL。

## 🐹 七、in
## 🐹 七、in :id=in

### 🏮 1. 方法介绍
### 🏮 1. 方法介绍 :id=in-methods

`in` 系列的方法是用来拼接 `SQL` 中范围查询的系列方法,生成如:`u.sex in :u_sex` 这样的范围查询功能,主要包含如下方法:

Expand Down Expand Up @@ -343,7 +345,7 @@ orNotIn(String field, String name, Collection<?> values, boolean match) // v2.3.
- `values`,表示范围查询需要的参数的数组或集合;
- `match`,表示是否生成该SQL片段,值为`true`时生成,否则不生成;

### 🪔 2. 使用示例
### 🪔 2. 使用示例 :id=in-demo

!> **💡 注**:下面的示例仅是为了集中演示 `in` 的使用,具体 SQL 运行时的正确性,你不用特别在意。

Expand Down Expand Up @@ -372,9 +374,9 @@ assertEquals("u.sex IN :u_sex u.city IN :u_city u.sex IN :u_sex AND u.sex IN :u_
assertEquals(2, sqlInfo.getParams().size());
```

## 🐿️ 八、isNull
## 🐿️ 八、isNull :id=is-null

### 📖 1. 方法介绍
### 📖 1. 方法介绍 :id=is-null-methods

`isNull` 系列的方法是用来拼接 SQL 中判断字段为 `null` 值或不为 `null` 值情况的系列方法,生成如:`u.state IS NULL` 这样 SQL 片段的功能,主要包含如下方法:

Expand Down Expand Up @@ -410,7 +412,7 @@ orIsNotNull(String field, boolean match
- `field`,表示数据库字段或实体属性;
- `match`,表示是否生成该 SQL 片段,值为 `true` 时生成,否则不生成;

### 📕 2. 使用示例
### 📕 2. 使用示例 :id=is-null-demo

!> ****:下面的示例仅是为了集中演示 `isNull` 的使用,具体 SQL 运行时的正确性,你不用特别在意。

Expand Down Expand Up @@ -441,7 +443,7 @@ public void testIsNull() {
}
```

## 🐻 九、doAny
## 🐻 九、doAny :id=do-any

`doAny` 的两个方法主要用来方便你在链式拼接的过程中,来完成更多自定义、灵活的操作。`match` 意义和上面类似,值为 `true` 时才执行,`FenixAction` 是你自定义操作的函数式接口,执行时调用 `execute()` 方法,Java 8 及之后可以使用 `Lambda` 表达式来简化代码。

Expand All @@ -453,7 +455,7 @@ doAny(FenixAction action)
doAny(boolean match, FenixAction action)
```

### 📘 1. 使用示例
### 📘 1. 使用示例 :id=do-any-demo

下面是 `doAny` 的执行示例,供你参考。

Expand All @@ -468,7 +470,7 @@ SqlInfo sqlInfo = Fenix.start()
.end();
```

## 🐼 十、where
## 🐼 十、where :id=where

`where` 方法有几个重载方法,其中 `where(Consumer<Fenix> consumer)` 方法同 XML 中的 `<where></where>` 标签是用来处理动态 SQL 中的 `WHERE` 关键之后的 `AND` 或者 `OR` 关键字的情况。

Expand Down Expand Up @@ -497,7 +499,7 @@ where(Consumer<Fenix> consumer)
whereDynamic()
```

### 📗 1. 使用示例
### 📗 1. 使用示例 :id=where-demo

下面是动态 where(`whereDynamic()` 和 `where(Consumer<Fenix> consumer)`)的使用示例,供你参考。

Expand Down Expand Up @@ -527,7 +529,7 @@ SqlInfo sqlInfo = Fenix.start()
.end();
```

## 🦨 十一、综合性示例
## 🦨 十一、综合性示例 :id=comprehensive-example

下面是一个综合性的示例,来演示通过 Fenix 的链式 API 来拼接动态 SQL 的使用。

Expand Down
12 changes: 7 additions & 5 deletions docs/queryfenix-introduction.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
## 🚀 一、注解元数据介绍
# 🍓 @QueryFenix 注解 :id=title

## 🚀 一、注解元数据介绍 :id=metadata

- **`value()`**: 完整的 `fenix id` 标记,该值由 XML 文件的命名空间(`namespace`)、点(`.`)号和 Fenix XML 标签中的 fenix id 组成。如果 `namespace` 的值写成对应 `repository` 接口的全路径名,则该值可以不用写 `namespace``.`号,且如果 fenix id 与对应的查询方法名一样,那么 `value()` 值就可以为空。
- **`countQuery()`**: 表示查询分页查询情况下查询总记录数时需要执行的 SQL。该值仅分页查询时用到,值的规则同上面的 `value()` 一样,如果 `namespace` 的值写成对应 `repository` 接口的全路径名,则该值可以不用写 `namespace``.`号。
Expand All @@ -7,7 +9,7 @@
- **`method()`**: 表示通过 Java 来拼接 SQL 语句的提供类的方法。
- **`countMethod()`**: 表示通过 Java 来拼接分页查询时查询总记录数 SQL 语句的提供类的方法。

## 🚠 二、@QueryFenix 注解使用简化
## 🚠 二、@QueryFenix 注解使用简化 :id=simplified

之前的示例中 `@QueryFenix("BlogRepository.queryMyBlogs")` 注解的内容分别代表 XML 文件对应的命名空间 `namespace` 和 XML 标签的 `id` 属性值。如果你将 XML 文件中的 `namespace` 写成 `BlogRepository.java` 的全路径名 `com.blinkfox.fenix.example.repository.BlogRepository`,那么 `@QueryFenix` 注解就可以再简化一些,只写对应的 `fenixId` 即可。

Expand All @@ -34,7 +36,7 @@ Page<Blog> queryMyBlogs(@Param("ids") List<String> ids, @Param("blog") Blog blog
Page<Blog> queryMyBlogs(@Param("ids") List<String> ids, @Param("blog") Blog blog, Pageable pageable);
```

## 🛰️ 三、自动的分页总记录数查询及自定义
## 🛰️ 三、自动的分页总记录数查询及自定义 :id=auto-paging

上面的分页查询,我们没有设置自定义的查询总记录数的语句,依然可以正常分页。是因为 Fenix 帮你将上面 `SELECT` 语句块的查询结果换成了 `count(*)`,来查询总记录数。由于 JPA 中的分页和排序参数是单独设置的,所以,查询总记录数的 JPQL 语句中也不会有 `Order By` 这样的片段。

Expand Down Expand Up @@ -63,10 +65,10 @@ Page<Blog> queryMyBlogs(@Param("ids") List<String> ids, @Param("blog") Blog blog
Page<Blog> queryMyBlogs(@Param("ids") List<String> ids, @Param("blog") Blog blog, Pageable pageable);
```

## 🚁 四、nativeQuery 原生 SQL
## 🚁 四、nativeQuery 原生 SQL :id=native-query

同原生的 `@Query` 注解一样,你也可以在 `@QueryFenix` 注解中,通过将 `nativeQuery()` 的值来设置为 `true`,来表示你的 JPQL 语句是将使用原生 SQL 查询。

## 🪐 五、使用 Java 代码拼接 SQL
## 🪐 五、使用 Java 代码拼接 SQL :id=java-sql

关于如何用 Java 代码来拼接动态 SQL,请参看[后续篇章](java/example)
Loading

0 comments on commit ec7c8a7

Please sign in to comment.