[英]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.