数据分类
保存指令用于保存任意复杂的数据结构,为了便于讨论,我们有必要对数据结构的形状进行一个基本分类。
实体定义
Jimmer实体支持两种表示属性
-
@Id
: Jimmer的任何实体类型都必须定义的一个属性。技术层面的唯一标识,行业内称其为Surrogate Id
-
@Key: Jimmer建议为实体类型定义的多个属性。业务层面的唯一标识,行业内称其为
Natural Id
在本系列文章中,所有实体都定义了@Id
属性和@Key
属性,并让Id属性使用数据库的自动编号作为自动增长策略。这里仅以Book
为例示范如下
- Java
- Kotlin
Book.java
@Entity
public interface Book {
@Id ❶
@GeneratedValue(strategy = GenerationType.IDENTITY) ❷
long id();
@Key ❸
String name();
@Key ❸
int edition();
BigDecimal price();
...省略其他属性...
}
Book.kt
@Entity
interface Book {
@Id ❶
@GeneratedValue(strategy = GenerationType.IDENTITY) ❷
val id: Long
@Key ❸
val name: String
@Key ❸
val edition: Int
val price: BigDecimal
...省略其他属性...
}
- ❶ Id属性, 即Surrogate Id
- ❷ Id属性采用数据库自动编号作为自动增长策略
- ❸ Key属性,即Natural Id
数据分类
1. Wild对象
如果一个对象的@Id
属性 (本文的Book.id
) 和 @Key
属性 (本文的Book.name
和Book.edition
) 都没有被指定,就被称为wild对象。例如
- Java
- Kotlin
Book book = Immutables.createBook(draft -> {
draft.setPrice(new BigDecimal("59.9"));
});
val book = Book {
price = BigDecimal("59.9")
}
这里所谓的@Key
属性没有被指定,包含两种情况
- 实体类型根本没有定义
@Key
属性 (本文案例未讨论) - 虽然实体类型定义可
@Key
属性,但对象的相关属性被没有被指定
警告
Jimmer不推荐Wild对象,虽然调节API参数可以保存wild对象,但终归会导致幂等性被破坏。
2. Id-specified对象
如果一个对象的@Id
属性 (本文的Book.id
) 被指定,就被称为id-specified对象。例如
- Java
- Kotlin
Book book = Immutables.createBook(draft -> {
draft.setId(17L);
...省略其他设置...
});
val book = Book {
id = 17L
...省略其他设置...
}
Jimmer支持UPSERT
操作,即,用户并不明确指定insert
或update
,让Jimmer自行判断。
如果用UPSERT
模式保存id-specified对象,那么Jimmer通过@Id
属性判断数据库中是否已经存在相应数据,最终决定应该insert还是update。
3. Key-specified对象
对于一个对象而言,如果@Id
属性 (本文的Book.id
) 没有被指定,但是其@Key
属性 (本文的Book.name
和Book.edition
) 被指定了,
那么该对象为key-specified对象,例如
- Java
- Kotlin
Book book = Immutables.createBook(draft -> {
draft.setName("GraphQL in Action");
draft.setEdition(2);
...省略除了id外的其他属性的设置...
});
val book = Book {
name = "GraphQL in Action"
edition = 1
...省略除了id外的其他属性的设置...
}