根对象保存模式
保存模式
保存指令支持5种保存模式,控制聚合根本身的保存方式
-
UPSERT: 这是默认的模式。先通过查询判断被保存的聚合根对象是否存在:
-
如果不存在:执行INSERT语句
-
如果存在:执行UPDATE语句
-
-
INSERT_ONLY: 无条件执行INSERT语句
-
INSERT_IF_ABSENT:
-
如果数据已经存在,忽略操作
-
否则,插入数据
-
-
UPDATE_ONLY: 无条件执行UPDATE语句
-
NON_IDEMPOTENT_UPSERT (不推荐):
-
如果对象的@Id属性或@Key属性被指定,执行与UPSERT等价的行为
-
否则,执行INSERT操作
-
警告
保存模式仅影响聚合根对象,不影响其他关联对象。
对于关联对象而言,请参考关联对象保存模式。
1. INSERT_ONLY
INSERT_ONLY
表示无条件插入数据
- Java
- Kotlin
List<Book> books = Arrays.asList(
Immutables.createBook(draft -> {
draft.setName("SQL in Action");
draft.setEdition(3);
draft.setPrice(new BigDecimal("49.9"));
draft.setStoreId(2L);
}),
Immutables.createBook(draft -> {
draft.setName("LINQ in Action");
draft.setEdition(2);
draft.setPrice(new BigDecimal("39.9"));
draft.setStoreId(2L);
})
);
List<Long> allocatedIds = sqlClient
.saveEntities(
books,
SaveMode.INSERT_ONLY
)
.getItems()
.stream()
.map(item -> item.getModifiedEntity().id())
.collect(Collectors.toList());
System.out.println("Allocated ids: " + allocatedIds);
val books = listOf(
Book {
name = "SQL in Action"
edition = 3
price = BigDecimal("49.9")
storeId = 2L
},
Book {
name = "SQL in Action"
edition = 2
price = BigDecimal("39.9")
storeId = 2L
}
)
val allocatedIds = sqlClient
.saveEntities(
books,
SaveMode.INSERT_ONLY
)
.items
.map {
it.modifiedEntity.id
}
println("Allocated ids: $allocatedIds")
INSERT_ONLY的工作方式非常简单,不做任何判断,无条件插入。
生成的批量操作SQL如下
insert into BOOK(NAME, EDITION, PRICE, STORE_ID) values(?, ?, ?, ?)
/* batch-0: SQL in Action, 3, 49.9, 2 */
/* batch-1: [LINQ in Action, 2, 39.9, 2 */
这个例子中,由于id属性对应的列采用了数据自动编号。因此批量插入完成后,数据库为所有数据分配的id都将被返回,打印结果为
Allocated ids: [100, 101]
2. UPDATE_ONLY
INSERT_ONLY
表示无条件更新数据,分为两种情况
-
对于Id-Specified对象而言,按照id修改数据
-
对于制定Key-Specified而言,按照key修改数据
按照id更新数据
- Java
- Kotlin
List<Book> books = Arrays.asList(
Immutables.createBook(draft -> {
draft.setId(3L); // Matched
draft.setName("SQL in Action");
draft.setEdition(3);
draft.setPrice(new BigDecimal("49.9"));
draft.setStoreId(2L);
}),
Immutables.createBook(draft -> {
draft.setId(100L); // Not matched
draft.setName("LINQ in Action");
draft.setEdition(2);
draft.setPrice(new BigDecimal("39.9"));
draft.setStoreId(2L);
})
);
BatchSaveResult<Book> result = sqlClient
.saveEntities(
books,
SaveMode.UPDATE_ONLY
);
System.out.println("Affected row count: " + result.getTotalAffectedRowCount());
val books = listOf(
Book {
id = 3L
name = "SQL in Action"
edition = 3
price = BigDecimal("49.9")
storeId = 2L
},
Book {
id = 100L
name = "SQL in Action"
edition = 2
price = BigDecimal("39.9")
storeId = 2L
}
)
val result = sqlClient
.saveEntities(
books,
SaveMode.UPDATE_ONLY
)
println("Affected row count: ${result.totalAffectedRowCount}")
对象的id属性被指定,因此根据对象的id来更新对象,生成的批量操作SQL如下
update BOOK
set
NAME = ?,
EDITION = ?,
PRICE = ?,
STORE_ID = ?
where
ID = ?
/* batch-0: [SQL in Action, 3, 49.9, 2, 3] *
/* batch-1: [LINQ in Action, 2, 39.9, 2, 100] */
该批量操作修改企图两条数据,假设数据库只有一条匹配数据,打印结果为1
。
按照key更新数据
假设Book实体定义如下
- Java
- Kotlin
Book.java
@Entity
public interface Book {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
long id();
@Key
String name();
@Key
int edition();
...省略其他既非id也非key的属性...
}
Book.kt
@Entity
public interface Book {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
val id: Long
@Key
val name: String
@Key
val edition: Int
...省略其他既非id也非key的属性...
}
这里Book.name
和Book.edition
被@Key修饰。
- Java
- Kotlin
List<Book> books = Arrays.asList(
Immutables.createBook(draft -> {
// Id is not specified
draft.setName("Learning GraphQL");
draft.setEdition(3);
draft.setPrice(new BigDecimal("49.9"));
draft.setStoreId(2L);
}),
Immutables.createBook(draft -> {
// Id is not specified
draft.setName("LINQ in Action");
draft.setEdition(2);
draft.setPrice(new BigDecimal("39.9"));
draft.setStoreId(2L);
})
);
BatchSaveResult<Book> result = sqlClient
.saveEntities(
books,
SaveMode.UPDATE_ONLY
);
for (MutationResultItem<Book> item : result.getItems()) {
if (ImmutableObjects.isLoaded(item.getModifiedEntity(), BookProps.ID)) {
System.out.println("Data is updated, updated id is " + item.getModifiedEntity().id());
} else {
System.out.println("Data is not updated");
}
}
val books = listOf(
Book {
// Id is not specified
name = "Learning GraphQL"
edition = 3
price = BigDecimal("49.9")
storeId = 2L
},
Book {
// Id is not specified
name = "SQL in Action"
edition = 2
price = BigDecimal("39.9")
storeId = 2L
}
)
val result = sqlClient
.saveEntities(
books,
SaveMode.UPDATE_ONLY
)
for (item in result.item) {
if (isLoaded(item.modifiedEntity, Book::id)) {
println("Data is updated, updated id is ${item.isModified}")
} else {
println("Data is not updated")
}
}
对象的id属性没有指定,因此根据对象的key来更新对象,生成的批量操作SQL如下
update BOOK
set
PRICE = ?,
STORE_ID = ?
where
NAME = ?
and
EDITION = ?
/* batch-0: [49.9, 2, Learning GraphQL, 3] */
/* batch-1: [39.9, 2, LINQ in Action, 2] */
打印结果为
Data is updated, updated id is 3
Data is not updated