[英]Spring Jpa Bulk Insert whole data or Update some fields of entity if already available
問題:我有一個正在運行的進程,它會定期從外部抓取 500 條記錄並將其插入數據庫。 如何使用 spring JPA 在以下情況下有效檢查,
或者
如何使用 Spring JPA 對所有列或僅選定列的批量記錄進行保存或更新?
如果您查看Spring Data JPA
的源代碼,您會發現:
@Transactional
public <S extends T> S save(S entity) {
if (entityInformation.isNew(entity)) {
em.persist(entity);
return entity;
} else {
return em.merge(entity);
}
}
save
操作是添加和更新的混合。 因此,通過使用save()
或saveAll()
方法,您已經實現了saveOrUpdate
的 function。
要更好地控制上述 upsert 行為,您可以在實體 class 上使用@DynamicUpdate
注釋,這意味着由 JPA 生成的更新 SQL 將僅訪問更改的列。
以上信息不足以在您的情況下正確使用 JPA。 如果選擇 JPA,則必須以object
方式進行數據庫訪問。 要處理 500 條記錄, unique
信號必須由以下條件之一定義:
我建議您使用第二個,因為主鍵用於在數據庫級別標記唯一性。 然后,使用 JPA,您應該在數據庫中找到新的 500 條記錄中存在的數據,更新它們修改的列,使用saveAll()
更新它們。 然后處理左側部分,構建實體並使用saveAll()
插入它們。
您可能已經注意到我上面使用compare and update then save operation in memory
不是原子的,並且在插入重復數據時可能會導致ConstraintViolationException
,有兩種處理方法:
synchronized
關鍵字或分布式鎖來使整個操作同步。 老實說,我對批量 upsert 上的 JPA 不滿意,它不是原子的,不安全的,也不快。 我認為這是因為在所有 DBMS 中都沒有普遍實現的upsert
模式,因此 ORM 部分放棄了 function。 我真誠地建議您對系統選擇的數據庫實現的原始 SQL 使用upsert
操作,例如 MYSQL INSERT... ON DUPLICATE KEY UPDATE Statement 。 下面的示例代碼:
public int upsert(List<Employee> employees) {
String sqlPattern = "INSERT INTO employee (id, code, name)\n"
+ "VALUES %s\n"
+ "ON DUPLICATE KEY UPDATE name = values(name);";
List<String> values = employees.stream()
// build something like (1, '10001', 'Foo Bar')
.map(employee -> buildRecord(employee))
.collect(Collectors.toList());
String sql = String.format(sqlPattern, StringUtils.join(values, ", "));
return jdbcTemplate.update(sql, Map.of());
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.