DTO查询
之前我们介绍了,利用对象抓取器灵活控制被查询数据结构的形状。
现在,我们介绍一个与之等价的功能:查询DTO对象。
Jimmer提供了DTO语言。
该语言本质上是对象抓取器的另外一种表达方式
利用该语言,开发人员可以快速以某个实体类型为聚合根定义多种数据结构的形状,编译器会为每种形状定义生成相应的Java/Kotlin DTO类。每个DTO类型都包含和原动态类型之间的彼此转化逻辑,以及一个和自身形状匹配的对象抓取器。
某些情况下,服务端查询出某种形状的数据后,并不是为了作为HTTP请求的返回,而是自己用,用来驱动后续的复杂的业务逻辑,这是采用这种方式的理想场合。
注意,如果服务端查询某种形状的数据不是为了自己用,而是为了直接作为HTTP请求的返回值,则更推荐直接返回动态实体对象,并利用客户端篇中的方案自动生成开发体验很高的客户端代码。
定义DTO的形状
本文侧重于讲解如何查询静态DTO类型,并 非系统性介绍DTO语言,请参考对象篇/DTO转换/DTO语言以了解完整的DTO语言。
假如Book
类的全名为com.yourcompany.yourproject.model.Book
,你可以
-
在实体定义所在项目中,建立目录
src/main/dto
-
在
src/main/dto
下,建立文件Book.dto
-
编辑此文件,利用DTO语言,定义Book实体的各种DTO形状
Book.dtoexport com.yourcompany.yourproject.model.Book
-> package com.yourcompany.yourproject.model.dto
BookDetailView {
#allScalars
store {
#allScalars
}
authors {
#allScalars
}
}
SimpleBookView { ...略... }
...省略其他DTO形状定义...
自动生成DTO类型
Jimmer负责编译dto文件,自动生成符合这些形状的DTO类型。
如果除了dto文件外还有其他Java/Kotlin原代码文件被修改了,直接点击IDE中运行按钮可以导致dto文件的重新编译
但是,如果除了dto文件外没有其他Java/Kotlin文件被修改,简单地点击IDE中运行按钮并不会导致dto文件被重新编译,除非显式地rebuild!
如果你使用的构建工具是Gradle,也可以使用社区提供的第三方Gradle插件来解决这个问题: jimmer-gradle
以上面代码中的BookDetailView
为例,此dto文件被Jimmer成功编译后,会自动生成如下DTO类型
- Java
- Kotlin
package com.yourcompany.yourproject.model.dto;
import com.yourcompany.yourproject.model.Book;
import org.babyfish.jimmer.View;
@GeneratedBy(file = "<your_project>/src/main/dto/Book.dto")
public class BookDetailView implements Input<Book> {
private long id;
private String name;
private int edition;
private BigDecimal price;
private TargetOf_store store;
private List<TargetOf_authors> authors;
public static class TargetOf_store implements Input<BookStore> {
private long id;
private String name;
@Nullable
private String website;
...省略其他成员...
}
public static class TargetOf_authors implements Input<Author> {
private long id;
private String firstName;
private String lastName;
private Gender gender;
...省略其他成员...
}
...省略其他成员...
}
package com.yourcompany.yourproject.model.dto
import com.yourcompany.yourproject.model.Book
import org.babyfish.jimmer.View
@GeneratedBy(file = "<your_project>/src/main/dto/Book.dto")
data class BookDetailView(
val id: Long = 0,
val name: String = "",
val edition: Int = 0,
val price: BigDecimal,
val store: TargetOf_store? = null,
val authors: List<TargetOf_authors> = emptyList(),
) : Input<Book> {
data class TargetOf_store(
val id: Long = 0,
val name: String = "",
val website: String? = null,
) : Input<BookStore> {
...省略其他成员...
}
data class TargetOf_authors(
val id: Long = 0,
public val firstName: String = "",
public val lastName: String = "",
public val gender: Gender,
) : Input<Author> {
...省略其他成员...
}
...省略其他成员...
}
-
生成的DTO类所在的包并非实体所处的包,而是其
dto
子包 -
对于Java而言,假设用户已经使用了lombok