Skip to content

Commit

Permalink
新增了两篇新文档,修改了一些文档
Browse files Browse the repository at this point in the history
  • Loading branch information
blinkfox committed Dec 10, 2020
1 parent 4950afb commit fe6661a
Show file tree
Hide file tree
Showing 7 changed files with 259 additions and 14 deletions.
2 changes: 1 addition & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@

同时,Fenix 还提供了 Java 链式 `API` 书写动态 SQL 和动态 `Specification` 的方式,使 SQL 可读性和紧凑性更好。还可以使用动态条件注解将查询条件的实体 Bean 中标记对应的查询条件注解,而获得动态的查询能力。如果要书写静态或动态的中、长 SQL,则推荐使用 `XML` 方式,便于集中阅读、调试和维护 SQL。

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

Expand Down
4 changes: 2 additions & 2 deletions docs/_sidebar.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
- [🍜 自定义条件注解](sp-bean/custom-annotation)
- 🛰️ 增强的【增删改】
- [🚀 更高效的【批量增删改】](cud/fast-batch-cud)
- [🚁 非【null】属性的增量更新]()
- [✈️ 更多的主键 ID 生成策略]()
- [🚁 非【null】属性的增量更新](cud/not-null-update)
- [✈️ 更多的主键 ID 生成策略](cud/id-generator)
- [🍬 更多功能](more-features)
- [🍹 版本更新记录](CHANGELOG)
14 changes: 7 additions & 7 deletions docs/cud/fast-batch-cud.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# 🚀 更高效的【批量增删改】

## 一、JPA 中自带的优化配置
## 💐 一、JPA 中自带的优化配置

在 Spring Data JPA 中批量保存或更新的 `saveAll` 方法性能较低。但是,Spring Data JPA(或者说 `Hibernate`)中也自带了关于批量操作的优化配置,通常默认没有开启,我建议你开启这些配置项。

Expand All @@ -19,13 +19,13 @@ spring:
batch_versioned_data: true
```
## 二、Fenix 中【批量增删改】的增强
## 🌻 二、Fenix 中【批量增删改】的增强
### 1. 如何使用
### 🍺 1. 如何使用
Fenix 在 `2.4.0` 版本中提供了相比 `saveAll` 更高效的**批量新增**、**批量更新**和**批量删除**的方法。但是,Fenix 中并没有提供类似于 `saveAll` 这种能同时做到批量新增或者更新的方法,而是为了提高效率,对批量新增和批量更新的方法单独进行了实现和优化。这样即能保证对 JPA 的兼容性,又能提高各自处理场景的效率。需要开发人员可以根据自己的业务场景选择对应的方法。

要使用这些方法,只须要让你业务功能的 `Repository` 接口集成自 `FenixJpaRepository` 接口即可。由于 `FenixJpaRepository` 接口继承自 `JpaRepository` 接口,所以 `FenixJpaRepository` 接口的功能完全兼容你以前所使用的 `JpaRepository` 的接口。
要使用这些方法,只须要让你业务功能的 `Repository` 接口继承自 `FenixJpaRepository` 接口即可。由于 `FenixJpaRepository` 接口继承自 `JpaRepository` 接口,所以 `FenixJpaRepository` 接口的功能完全兼容你以前所使用的 `JpaRepository` 的接口。

使用示例如下:

Expand All @@ -42,7 +42,7 @@ public interface SchoolRepository extends FenixJpaRepository<School, String> {
}
```

### 2. 批量新增(saveBatch)
### 🥤 2. 批量新增(saveBatch)

**批量新增**有两个重载方法:

Expand All @@ -68,7 +68,7 @@ public void testSaveBatch() {
}
```

### 3. 批量更新(updateBatch)
### 🍹 3. 批量更新(updateBatch)

**批量更新**也有两个重载方法:

Expand All @@ -94,7 +94,7 @@ public void testUpdateBatch() {
}
```

### 4. 批量删除(deleteBatchByIds)
### 🧃 4. 批量删除(deleteBatchByIds)

Spring Data JPA 中已经有相关批量删除的方法了,比如:

Expand Down
186 changes: 186 additions & 0 deletions docs/cud/id-generator.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
# ✈️ 更多的主键 ID 生成策略

## 🆔 一、简介

Fenix 从 `2.4.0` 版本开始新增了三种主键 `ID` 的生产策略类供你选择和使用,同时也支持你通过 Java API 去调用生成 `ID`

- **❄️ 雪花算法 ID** (`Long` 长整型)
- **☃️ 62 进制雪花算法 ID** (`String` 字符串型)
- **🌟 62 进制 UUID** (`String` 字符串型)

## ❄️ 二、雪花算法的 ID 生成策略

雪花算法 (`snowflake`) 已经是现在使用比较广泛的 ID 生成算法,其避免了 `UUID` 的冗长无序的缺点,生成的 ID 是**整体有序****长整型**数据,Fenix 中也默认做了集成和支持。

雪花算法生成的 ID 示例:`2458424618421248`

在 JPA 中要使用自定义的 `ID` 生成策略,需要在你的实体类的 ID 字段中标注 `@GeneratedValue``@GenericGenerator` 两个注解,并保证 `@GeneratedValue` 注解中的 `generator` 属性和 `@GenericGenerator` 注解中的 `name` 属性值相同。且 `@GenericGenerator` 注解中的 `strategy` 属性值为:`com.blinkfox.fenix.id.SnowflakeIdGenerator`

使用方式示例如下:

```java
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.GenericGenerator;

@Getter
@Setter
@Entity
@Table(name = "t_my_entity")
public class MyEntity {

/**
* 使用 Fenix 中的雪花算法 ID 生成策略.
*/
@Id
@Column(name = "c_id")
@GeneratedValue(generator = "snowflake")
@GenericGenerator(name = "snowflake", strategy = "com.blinkfox.fenix.id.SnowflakeIdGenerator")
private Long id;

/**
* 名称.
*/
@Column(name = "c_name")
private String name;

// 下面省略了其它字段.

}
```

## ☃️ 三、62 进制雪花算法的 ID 生成策略

如果你的 ID 不是长整型(`Long`)的,是字符串类型(`String`)的,为了能缩短雪花算法 ID 字符串的长度,可以将原来长度为 `16` 位的雪花算法 ID 的转换为 `62` 进制,能大幅度缩短 `ID` 的长度为 `9` 位,且依然能保证**唯一性****整体有序性**

62 进制雪花算法生成的字符串型 ID 示例:`BG5skT7pI`

`@GenericGenerator` 注解中的 `strategy` 属性值为:`com.blinkfox.fenix.id.Snowflake62RadixIdGenerator`

使用方式示例如下:

```java
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.GenericGenerator;

@Getter
@Setter
@Entity
@Table(name = "t_my_entity")
public class MyEntity {

/**
* 使用 Fenix 中的雪花算法 ID 生成策略.
*/
@Id
@Column(name = "c_id")
@GeneratedValue(generator = "snowflake62Radix")
@GenericGenerator(name = "snowflake62Radix", strategy = "com.blinkfox.fenix.id.Snowflake62RadixIdGenerator")
private String id;

/**
* 名称.
*/
@Column(name = "c_name")
private String name;

// 下面省略了其它字段.

}
```

在 Fenix 中,你也可以通过 Java API 调用生成 `UUID` 和 62 进制的 `UUID`,API 示例如下:

```java
// 使用 IdWorker 来静态方法调用获取通常的 UUID,示例:'73b037d12c894a8ebe673fb6b1caecac'.
String uuid = IdWorker.getUuid();

// 使用 IdWorker 来静态方法调用获取 62 进制的简短 UUID,示例:'FXOedrCvouduYPlYgul'.
String uuid2 = IdWorker.get62RadixUuid();
```

## 🌟 四、62 进制 UUID 生成策略

鉴于 `UUID` 本质上是 `16` 进制的字符串,字符串长度为 `32` 位,依然可以通过进制转换,将其转换为 `62` 进制,能大幅度缩短 `UUID` 的字符串长度为 `19` 位,且依然能保证**唯一性****无序性**

假如原 16 进制的 UUID 为:`73b037d12c894a8ebe673fb6b1caecac`,那么转换后的 62 进制 `UUID` 的字符串示例为:`FXOedrCvouduYPlYgul`

`@GenericGenerator` 注解中的 `strategy` 属性值为:`com.blinkfox.fenix.id.Uuid62RadixIdGenerator`

使用方式示例如下:

```java
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.GenericGenerator;

@Getter
@Setter
@Entity
@Table(name = "t_my_entity")
public class MyEntity {

/**
* 使用 Fenix 中的雪花算法 ID 生成策略.
*/
@Id
@Column(name = "c_id")
@GeneratedValue(generator = "uuid62Radix")
@GenericGenerator(name = "uuid62Radix", strategy = "com.blinkfox.fenix.id.Uuid62RadixIdGenerator")
private String id;

/**
* 名称.
*/
@Column(name = "c_name")
private String name;

// 下面省略了其它字段.

}
```

## ☕ 五、通过 Java API 获取 ID

在 Fenix 中,你也可以通过 Java API 调用生成雪花算法的 ID 或 `UUID`

以下是生成雪花算法 ID 的 API 方法:

```java
private static final IdWorker idWorker = new IdWorker();

// 获取 10 进制长整型的雪花算法 ID(仅由数字组成).
long id = idWorker.getId();

// 获取 36 进制字符串型的雪花算法 ID(由数字 + 26 位小写字母组成).
String id2 = idWorker.get36RadixId();

// 获取 62 进制字符串型的雪花算法 ID(由数字 + 26 位小写字母 + 26 位大写字母组成).
String id3 = idWorker.get62RadixId();
```

以下是通过 Java 静态方法去生成通常的 `UUID` 和 62 进制 `UUID` 的方法:

```java
// 使用 IdWorker 来静态方法调用获取通常的 UUID,示例:'73b037d12c894a8ebe673fb6b1caecac'.
String uuid = IdWorker.getUuid();

// 使用 IdWorker 来静态方法调用获取 62 进制的简短 UUID,示例:'FXOedrCvouduYPlYgul'.
String uuid2 = IdWorker.get62RadixUuid();
```
58 changes: 58 additions & 0 deletions docs/cud/not-null-update.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# 🚁 非【null】属性的增量更新

## 🍀 一、初衷

在实际业务场景中,更新数据时,从前端得到的对象实体信息数据的参数中,部分信息是不为空,而我们业务上也只想更新这些不为空的字段到数据库中,而不是将空的数据也一起覆盖保存到数据库中,否则就会造成部分字段数据丢失的问题。

Fenix 在 `2.4.0` 版本中增加了这种常见业务操作的功能处理。

## 🍁 二、如何使用

首先,你须要让你业务功能的 `Repository` 接口继承自 `FenixJpaRepository` 接口。由于 `FenixJpaRepository` 接口继承自 `JpaRepository` 接口,所以 `FenixJpaRepository` 接口的功能完全兼容你以前所使用的 `JpaRepository` 的接口。

使用示例如下:

```java
/**
* 学校(School)相关操作的 Repository 接口.
*
* @author blinkfox on 2020-12-05.
* @since v2.4.0
*/
@Repository
public interface SchoolRepository extends FenixJpaRepository<School, String> {

}
```

### 🍂 三、方法介绍

**`null` 属性的增量更新**有两个方法:

- `S saveOrUpdateByNotNullProperties(S entity)`: 新增实体或更新实体类中非 `null` 属性的字段值。本方法保存每条数据时会先查询判断是否存在,再进行插入或者更新。
- `void saveOrUpdateAllByNotNullProperties(Iterable<S> entities)`: 新增或更新所有实体类中非 `null` 属性的字段值,本方法仅仅是上面方法的 `for` 循环版本,提供了循环处理的功能。

> **💡 注**
> 1. 上面两个方法的主要判断处理逻辑为:如果传入的实体主键 `ID` 为空,说明是新增的情况,就插入一条新的数据;如果实体的主键 `ID` 不为空,会先判断是否存在该 `ID` 的数据,如果不存在,也会新增插入一条数据;否则说明是更新的情况,会仅更新保存实体类属性中不为 `null` 值的属性字段到数据库中;
> 2. 由于实际场景中难以区分空和 `null` 的关系,为了统一处理以及不和一些业务场景产生冲突,Fenix 中约定仅更新字段值不为 `null` 的值,如果实体对象中的属性值是空字符串`""`或者 `0` 等等,那么也认为是不为 `null` 的,视为业务上就是要保存空字符串值或者 `0`。所以,Fenix 中也会将该空字符串的值更新到数据库中。所以,**建议你的实体类中所有属性的类型都是对象包装类型,不要用 Java 中的 8 种原生基础类型**
简单的使用示例如下:

```java
@Autowired
private SchoolRepository schoolRepository;

/**
* 测试 saveBatch 方法.
*/
@Transactional(rollbackFor = RuntimeException.class)
public void testSaveBatch() {
// 构造要更新的数据,这里表示只更新 id 为 '123' 的数据的 name 值为 '北京大学'.
List<School> schools = new School()
.setId("123")
.setName("北京大学");

// 增量更新数据.
fenixSchoolRepository.saveOrUpdateByNotNullProperties(school);
}
```
8 changes: 5 additions & 3 deletions docs/more-features.md
Original file line number Diff line number Diff line change
Expand Up @@ -261,15 +261,17 @@ Map<String, Object> context = ParamWrapper.newInstance("sex", "1").put("stuId",

## 🐞 五、表达式的真假判断

Fenix 中关于表达式字符串的真假判断在 `com.blinkfox.fenix.helper.ParseHelper` 类中提供了静态方法。

**主要方法**

```java
// 是否匹配,常用于标签中的 match 值的解析,即如果 match 不填写,或者内容为空,或者解析出为正确的值,都视为true.
isMatch(String match, Object context)
ParseHelper.isMatch(String match, Object context)

// 是否不匹配,同 isMatch 相反,只有解析到的值是 false 时,才认为是 false.
isNotMatch(String match, Object context)
ParseHelper.isNotMatch(String match, Object context)

// 是否为 true,只有当解析值确实为 true 时,才为 true.
isTrue(String exp, Object context)
ParseHelper.isTrue(String exp, Object context)
```
1 change: 0 additions & 1 deletion src/test/java/com/blinkfox/fenix/entity/EntityOne.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
Expand Down

0 comments on commit fe6661a

Please sign in to comment.