release 1.4.0-R1

This commit is contained in:
linpeilie 2024-03-15 18:05:20 +08:00
parent 182bc024da
commit 155575096c
14 changed files with 246 additions and 7 deletions

View File

@ -23,6 +23,7 @@ export const series = {
{ text: 'Map 转对象', link: '/guide/map-to-class' },
{ text: '枚举转换', link: '/guide/enum-convert' },
{ text: '一个类与多个类之间转换', link: '/guide/multiple-class-convert' },
{ text: '类循环嵌套', link: '/guide/cycle-avoiding' },
{ text: '类转换API', link: '/guide/converter-api' },
{ text: '配置项', link: '/guide/configuration' },
{ text: '常见问题', link: '/guide/faq' },

View File

@ -62,18 +62,26 @@ footer:
<dependency>
<groupId>io.github.linpeilie</groupId>
<artifactId>mapstruct-plus-spring-boot-starter</artifactId>
<version>1.3.6</version>
<version>1.4.0-R1</version>
</dependency>
```
- gradle
```groovy
implementation group: 'io.github.linpeilie', name: 'mapstruct-plus-spring-boot-starter', version: '1.3.6'
implementation group: 'io.github.linpeilie', name: 'mapstruct-plus-spring-boot-starter', version: '1.4.0-R1'
```
## 更新日志
### 1.4.0
- **优化复杂对象转换逻辑,占用元空间更小!性能更快!**
- 去除 hutool 等依赖,目前项目中只依赖了 MapStruct
- 适配对象循环嵌套场景
- [feature#63](https://github.com/linpeilie/mapstruct-plus/pull/63)`AutoMapping``ReverseAutoMapping` 支持 `qualifiedByName``conditionQualifiedByName``dependsOn` 属性
- [issue#I93Z2Z](https://gitee.com/easii/mapstruct-plus/issues/I93Z2Z)`AutoMappings` 支持配置在方法上面
### 1.3.6
- 兼容内部类转换

View File

@ -58,18 +58,26 @@ fotter:
<dependency>
<groupId>io.github.linpeilie</groupId>
<artifactId>mapstruct-plus-spring-boot-starter</artifactId>
<version>1.3.6</version>
<version>1.4.0-R1</version>
</dependency>
```
- gradle
```groovy
implementation group: 'io.github.linpeilie', name: 'mapstruct-plus-spring-boot-starter', version: '1.3.6'
implementation group: 'io.github.linpeilie', name: 'mapstruct-plus-spring-boot-starter', version: '1.4.0-R1'
```
## Change Log
### 1.4.0
- **Optimize complex object conversion logic, take up less meta-space! and faster!**
- Get rid of dependencies such as hutool, which currently only rely on MapStruct in the project.
- The adaptation object loop nesting scenario
- [feature#63](https://github.com/linpeilie/mapstruct-plus/pull/63) `AutoMapping``ReverseAutoMapping` supports `qualifiedByName`,`conditionQualifiedByName`,and `dependsOn` properties.
- [issue#I93Z2Z](https://gitee.com/easii/mapstruct-plus/issues/I93Z2Z) `AutoMappings` supports configuration on methods.
### 1.3.6
- Compatible with internal class conversion.

View File

@ -6,6 +6,14 @@ category:
description: MapStructPlus release log
---
### 1.4.0
- **Optimize complex object conversion logic, take up less meta-space! and faster!**
- Get rid of dependencies such as hutool, which currently only rely on MapStruct in the project.
- The adaptation object loop nesting scenario
- [feature#63](https://github.com/linpeilie/mapstruct-plus/pull/63) `AutoMapping``ReverseAutoMapping` supports `qualifiedByName`,`conditionQualifiedByName`,and `dependsOn` properties.
- [issue#I93Z2Z](https://gitee.com/easii/mapstruct-plus/issues/I93Z2Z) `AutoMappings` supports configuration on methods.
### 1.3.6
- Compatible with internal class conversion.

View File

@ -0,0 +1,82 @@
---
title: 类循环嵌套
order: 7
category:
- 指南
description: MapStructPlus MapStructPlus类循环嵌套 CycleAvoiding
---
## 背景
类循环嵌套是指两个类互相引用,例如,源对象和目标对象结构都包含父对象和子对象之间的双向关联。
当存在这种情况时直接进行转换时会导致栈溢出的问题stack overflow error
示例:
```java
@Data
public class TreeNode {
private TreeNode parent;
private List<TreeNode> children;
}
@Data
public class TreeNodeDto {
private TreeNodeDto parent;
private List<TreeNodeDto> children;
}
```
`parent` 属性可以是其他类型的,可能跨越一个更长的属性链形成的嵌套循环。
为了适配这种情况MapStructPlus 的 **`AutoMapper`** 注解中增加了 **`cycleAvoiding`** 属性,该属性用于标识,是否需要避免循环嵌套的问题。
默认为 `false`,如果需要避免循环嵌套,需要将该属性设置为 `true`
当配置为 `true` 时,在整个对象的转换过程链路中,会传递一个 `CycleAvoidingMappingContext` 对象,临时保存转换生成的对象,
在转换链路中,如果发现需要生成的对象已经存在,会直接返回该类型,从而避免栈溢出问题。
所以,配置该属性为 `true` 时,会有一点的性能消耗,如果没有循环嵌套的情况,使用默认配置即可,避免不必要的性能消耗。
## 使用示例
以上面的示例为例,在 `AutoMapper` 注解中,配置 `cycleAvoiding` 属性为 `true`,如下所示:
```java
@Data
@AutoMapper(target = TreeNodeDto.class, cycleAvoiding = true)
public class TreeNode {
private TreeNode parent;
private List<TreeNode> children;
}
@Data
@AutoMapper(target = TreeNode.class, cycleAvoiding = true)
public class TreeNodeDto {
private TreeNodeDto parent;
private List<TreeNodeDto> children;
}
```
编译生成的转换逻辑如下:
```java
public TreeNodeDto convert(TreeNode arg0, CycleAvoidingMappingContext arg1) {
TreeNodeDto target = arg1.getMappedInstance(arg0, TreeNodeDto.class);
if (target != null) {
return target;
}
if (arg0 == null) {
return null;
}
TreeNodeDto treeNodeDto = new TreeNodeDto();
arg1.storeMappedInstance(arg0, treeNodeDto);
treeNodeDto.setParent(demoConvertMapperAdapterForCycleAvoiding.iglm_TreeNodeToTreeNodeDto(arg0.getParent(), arg1));
treeNodeDto.setChildren(
demoConvertMapperAdapterForCycleAvoiding.iglm_TreeNodeToTreeNodeDto(arg0.getChildren(), arg1));
return treeNodeDto;
}
```

View File

@ -1,6 +1,6 @@
---
title: 常见问题
order: 7
order: 8
category:
- 指南
description: MapStructPlus MapStructPlus常见问题 faq

View File

@ -8,8 +8,26 @@ description: MapStructPlus Map转为对象 map convert to class
MapStructPlus 提供了更加强大的 `Map<String, Object>` 转对象的功能。
::: warning
MapStructPlus 1.4.0 及以后版本,不再内置 [Hutool](https://hutool.cn) 框架,如果需要用到该功能时,需要额外引入 `hutool-core` 依赖。
:::
## 使用
### 添加依赖
> 1.4.0 及以后的版本需要添加该依赖1.4.0之前的版本内置 hutool不需要额外添加。
```xml
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-core</artifactId>
<version>${hutool.version}</version>
</dependency>
```
### 添加注解
**当想要自动生成 `Map<String, Object>` 转为目标类的接口及实现类时,只需要在目标类上添加 `@AutoMapMapper` 注解**。
## 支持的 value 类型

View File

@ -6,6 +6,14 @@ category:
description: MapStructPlus release log
---
### 1.4.0
- **优化复杂对象转换逻辑,占用元空间更小!性能更快!**
- 去除 hutool 等依赖,目前项目中只依赖了 MapStruct
- 适配对象循环嵌套场景
- [feature#63](https://github.com/linpeilie/mapstruct-plus/pull/63)`AutoMapping``ReverseAutoMapping` 支持 `qualifiedByName``conditionQualifiedByName``dependsOn` 属性
- [issue#I93Z2Z](https://gitee.com/easii/mapstruct-plus/issues/I93Z2Z)`AutoMappings` 支持配置在方法上面
### 1.3.6
- 兼容内部类转换

View File

@ -18,7 +18,7 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<mapstruct.version>1.5.1.Final</mapstruct.version>
<mapstruct-plus.version>1.4.0</mapstruct-plus.version>
<mapstruct-plus.version>1.4.0-R1</mapstruct-plus.version>
<lombok.version>1.18.22</lombok.version>
<hutool.version>5.8.26</hutool.version>
</properties>

View File

@ -0,0 +1,27 @@
package io.github.linpeilie.mapper;
import org.mapstruct.Named;
import org.springframework.boot.context.properties.bind.Name;
import org.springframework.stereotype.Component;
@Component
@Named("TitleTranslator")
public class Titles {
@Named("EnglishToFrench")
public String translateTitleEF(String title) {
if ("One Hundred Years of Solitude".equals(title)) {
return "Cent ans de solitude";
}
return "Inconnu et inconnu";
}
@Named("FrenchToEnglish")
public String translateTitleFE(String title) {
if ("Cent ans de solitude".equals(title)) {
return "One Hundred Years of Solitude";
}
return "Unknown";
}
}

View File

@ -0,0 +1,15 @@
package io.github.linpeilie.model;
import io.github.linpeilie.annotations.AutoMapper;
import io.github.linpeilie.annotations.AutoMapping;
import io.github.linpeilie.mapper.Titles;
import lombok.Data;
@Data
@AutoMapper(target = FrenchRelease.class, uses = Titles.class)
public class EnglishRelease {
@AutoMapping(qualifiedByName = "EnglishToFrench")
private String title;
}

View File

@ -0,0 +1,15 @@
package io.github.linpeilie.model;
import io.github.linpeilie.annotations.AutoMapper;
import io.github.linpeilie.annotations.AutoMapping;
import io.github.linpeilie.mapper.Titles;
import lombok.Data;
@Data
@AutoMapper(target = EnglishRelease.class, uses = Titles.class)
public class FrenchRelease {
@AutoMapping(qualifiedByName = "FrenchToEnglish")
private String title;
}

View File

@ -2,7 +2,10 @@ package io.github.linpeilie;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import io.github.linpeilie.model.Car;
import io.github.linpeilie.model.EnglishRelease;
import io.github.linpeilie.model.FrenchRelease;
import io.github.linpeilie.model.Goods;
import io.github.linpeilie.model.GoodsDto;
import io.github.linpeilie.model.GoodsStateEnum;
@ -16,6 +19,8 @@ import io.github.linpeilie.model.SVO;
import io.github.linpeilie.model.Sku;
import io.github.linpeilie.model.SysMenu;
import io.github.linpeilie.model.SysMenuVo;
import io.github.linpeilie.model.TreeNode;
import io.github.linpeilie.model.TreeNodeDto;
import io.github.linpeilie.model.User;
import io.github.linpeilie.model.UserDto;
import io.github.linpeilie.model.UserVO;
@ -262,4 +267,48 @@ public class QuickStartTest {
System.out.println(sDto1);
}
@Test
public void testConditionQualifiedByName() {
TreeNode parent = new TreeNode();
// children
List<TreeNode> children = new ArrayList<>();
for (int i = 0; i < 1; i++) {
TreeNode child = new TreeNode();
child.setParent(parent);
children.add(child);
}
parent.setChildren(children);
TreeNodeDto treeNodeDto1 = converter.convert(parent, TreeNodeDto.class);
// children <2 时不进行转换
Assert.isNull(treeNodeDto1.getChildren());
for (int i = 0; i < 99; i++) {
TreeNode child = new TreeNode();
child.setParent(parent);
children.add(child);
}
TreeNodeDto treeNodeDto2 = converter.convert(parent, TreeNodeDto.class);
Assert.equals(treeNodeDto2.getChildren().size(), 100);
treeNodeDto2.getChildren().forEach(child -> {
Assert.equals(child.getParent(), treeNodeDto2);
});
}
@Test
public void testQualifiedByName() {
EnglishRelease englishRelease = new EnglishRelease();
englishRelease.setTitle("Algorithms, 4th Edition");
FrenchRelease frenchRelease1 = converter.convert(englishRelease, FrenchRelease.class);
Assert.equals(frenchRelease1.getTitle(), "Inconnu et inconnu");
englishRelease.setTitle("One Hundred Years of Solitude");
FrenchRelease frenchRelease2 = converter.convert(englishRelease, FrenchRelease.class);
Assert.equals(frenchRelease2.getTitle(), "Cent ans de solitude");
EnglishRelease englishRelease1 = converter.convert(frenchRelease1, EnglishRelease.class);
Assert.equals(englishRelease1.getTitle(), "Unknown");
frenchRelease2.setTitle("Cent ans de solitude");
EnglishRelease englishRelease2 = converter.convert(frenchRelease2, EnglishRelease.class);
Assert.equals(englishRelease2.getTitle(), "One Hundred Years of Solitude");
}
}

View File

@ -18,7 +18,7 @@
</modules>
<properties>
<mapstruct-plus.version>1.4.0</mapstruct-plus.version>
<mapstruct-plus.version>1.4.0-R1</mapstruct-plus.version>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>