MapStruct
简介
Jimmer拓展了MapStruct,支持使用mapstruct来完成Jimmer动态实体对象和静态DTO对象之间的相互转化。
注意事项
Jimmer的实体对象是动态的 (和Hibernate3引入的标量属性惰性化比较类似),这是较早的MapStruct未曾考虑过的模式。
和MapStruct交流后,MapStruct会从1.6.0开始支持这种行为。
因此,请尽可能使用1.6.0或更高版本的MapStruct。
优点
缺点
更推荐使用DTO语言,原因如下
-
不可忽略的开发成本
DTO语言为Jimmer量身定制的方案,开发效率是结合其他任何技术方案无法比拟的。
-
不太适合Output DTO
DTO语言自动生成的DTO类型具备内置的对象抓取器,因此可以作为查询的输出类型 (虽然不推荐),请参见:
然而,手动定义的DTO类型没有对应的对象抓取器定义,只支持和动态实体相互转化。 虽然可以为此手动定义对象抓取器,但是存在DTO和对象抓取器形状不一致的风险。 所以,不适合作为Output DTO。
-
Kotlin风险
依赖和预编译器
对于将静态POJO转化为Jimmer动态对象而言,MapStruct并不知道该如何构建Jimmer对象。因此
-
Jimmer本身的预编译器 (Java的
jimmer-apt或Kotlin的jimmer-ksp) 在Draft中生成了一个一些面向MapStruct的代码,让MapStruct可以通过其Builder模式构建Jimmer对象。 -
Jimmer扩展了MapStruct的Annotation Processor,该扩展让MapStruct利用生成的Draft中为MapStruct预留的能力构建Jimmer对象。
这个扩展叫做
jimmer-mapstruct-apt-
对于Java而言,
jimmer-mapstruct-apt被jimmer-apt所包含 -
对于Kotlin而言,需同时在maven或gradle配置文件中使用
jimmer-ksp和jimmer-mapstruct-apt。
-
你既可以使用Jimmer标准的构建方式,也可以采用社区提供的插件
-
用法一:使用Jimmer标准的构建方式
- Java(Maven)
- Java(Gradle)
- Kotlin(Gradle.kts)
pom.xml...省略其他代码...
<build>
<dependencies>
<dependency> ➀
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
<dependency> ➊
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${mapstruct.version}</version>
</dependency>
...省略其他依赖...
</dependencies>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.10.1</version>
<configuration>
<annotationProcessorPaths>
<path> ➁
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
<path> ➋
<groupId>org.babyfish.jimmer</groupId>
<artifactId>jimmer-apt</artifactId>
<version>${jimmer.version}</version>
</path>
<path> ➌
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${mapstruct.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
...省略其他代码...build.gradledependencies {
implementation "org.projectlombok:lombok:${lombok.version}" ➀
implementation "org.mapstruct:mapstruct:${mapstructVersion}" ➊
annotationProcessor "org.projectlombok:lombok:${lombok.version}" ➁
annotationProcessor "org.babyfish.jimmer:jimmer-apt:${jimmerVersion}" ➋
annotationProcessor "org.mapstruct:mapstruct-processor:${mapstructVersion}" ➌
...省略其他依赖...
}build.gradle.ktsplugins {
id("com.google.devtools.ksp") version "1.7.10-1.0.6"
kotlin("kapt") version "1.7.10"
...省略其他插件...
}
dependencies {
implementation("org.mapstruct:mapstruct:${mapstructVersion}") ➊
ksp("org.babyfish.jimmer:jimmer-ksp:${jimmerVersion}") ➋
kapt("org.mapstruct:mapstruct-processor:${mapstructVersion}") ➌
kapt("org.babyfish.jimmer:jimmer-mapstruct-apt:${jimmerVersion}") ⓐ
...省略其他依赖...
}
kotlin {
sourceSets.main {
kotlin.srcDir("build/generated/ksp/main/kotlin")
}
} -
用法二:使用社区提供的插件
https://github.com/ArgonarioD/gradle-plugin-jimmer
- Java(Gradle插件)
- Kotlin(Gradle插件)
build.gradleplugins {
id "tech.argonariod.gradle-plugin-jimmer" version "latest.release"
...省略其他插件...
}
jimmer {
version = "${jimmerVersion}"
...省略其他配置...
}
dependencies {
implementation "org.projectlombok:lombok:${lombok.version}" ➀
implementation "org.mapstruct:mapstruct:${mapstructVersion}" ➊
annotationProcessor "org.projectlombok:lombok:${lombok.version}" ➁
annotationProcessor "org.mapstruct:mapstruct-processor:${mapstructVersion}" ➍
// 不需要手动添加 org.babyfish.jimmer:jimmer-apt 的依赖
// 检测到 mapstruct-processor 时,插件会自动添加该依赖
...省略其他依赖...
}build.gradle.ktsplugins {
id("tech.argonariod.gradle-plugin-jimmer") version "latest.release"
id("com.google.devtools.ksp") version "1.7.10+"
kotlin("kapt") version "1.7.10"
...省略其他插件...
}
jimmer {
version = "${jimmerVersion}"
...省略其他配置...
}
dependencies {
implementation("org.mapstruct:mapstruct:${mapstructVersion}") ➊
kapt("org.mapstruct:mapstruct-processor:${mapstructVersion}") ➌
...省略其他依赖...
}信息当你引入了MapStruct的kapt依赖时,插件会自动引入
jimmer-mapstruct-apt的依赖。
这个例子中,我们假设Java中基于lombok编写静态POJO。
| 语言 | 位置 | 描述 |
|---|---|---|
| Java和Kotlin | ➊ | 引入mapstruct依赖,让用户代码可以使用mapstruct的注解 |
| ➋ | 使用Jimmer的预编译器为动态类型生成相关的源代码,Java使用jimmer-apt,Kotlin使用jimmer-ksp | |
| ➌ | 使用mapstruct的annotation processor生成源代码 (后文会介绍) | |
| 仅Java | ➀ | 引入lombok的依赖,让用户代码可以使用lombok的注解 |
| ➁ | 使用Lombok的预编译器更改静态POJO类的代码,比如添加getter, setter | |
| 仅Kotlin | ⓐ | 使用jimmer-mapstruct-apt拓展➌ |
定义POJO
- Java
- Kotlin
@Data
public class BookInput {
@Nullable
private Long id;
private String name;
private int edition;
private BigDecimal price;
@Nullable
private Long storeId;
private List<Long> authorIds;
}
data class BookInput(
val id: Long? = null,
val name: String,
val edition: Int,
val price: BigDecimal,
val storeId: Long?,
val authorIds: List<Long>
)
Java POJO代码中采用了@Nullable注解,仅为提高可读性,无实质性功能
该POJO有三个属性,需要说明一下
-
BookInput.id-
这里,
BookInput.id
-