问题:我有一个进程正在运行,它会定期从外部获取500条记录并将其插入数据库。如何使用spring jpa有效地检查下面的案例,如果没有记录(非主键列也是唯一的),如何插入数据?如果有记录,如何只更新一些字段?或如何使用springjpa对所有列或仅选定列上的批量记录进行saveorupdate?
v1l68za41#
如果你查一下 Spring Data 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 .要更好地控制上述upsert行为,可以使用 @DynamicUpdate 实体类上的注解,这意味着jpa生成的updatesql将只访问更改的列。以上信息不足以在您的情况下正确使用jpa。如果选择jpa,则必须在 object 是的。为了处理这500条记录 unique 必须由以下条件之一定义:主键唯一约束我建议您使用第二个,因为主键用于在数据库级别标记unique。然后,使用jpa,您应该在数据库中找到新的500条记录中存在的数据,更新它们的修改列,使用 saveAll() 更新它们。然后处理左边的部分,构建实体并使用 saveAll() 插入它们。你可能已经注意到 compare and update then save operation in memory 我上面使用的方法不是原子的,可能会导致 ConstraintViolationException 插入重复数据时,有两种处理方法:如果数据不是那么严重,您可以只执行上述操作,但为异常的发生保留一些空间,您可以记录信息以进行手动修复,也可以不执行任何操作。但是记住捕获异常,不要使更新操作回滚。如果您确实对数据很认真,那么可以使用 synchronized 关键字或分布式锁。老实说,我对批处理upsert上的jpa不满意,它不原子,不安全,也不快。我认为这是因为没有一个通用的 upsert 模式,从而orm部分放弃了该功能。我真诚地推荐你使用 upsert 使用系统选择的数据库实现的原始sql操作,如mysql insert。。。重复键更新语句。示例代码如下:
save
save()
saveAll()
saveOrUpdate
@DynamicUpdate
object
unique
compare and update then save operation in memory
ConstraintViolationException
synchronized
upsert
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()); }
1条答案
按热度按时间v1l68za41#
如果你查一下
Spring Data JPA
,您将发现:这个
save
操作是添加和更新的混合。所以用这个方法save()
或者saveAll()
,您已经实现了saveOrUpdate
.要更好地控制上述upsert行为,可以使用
@DynamicUpdate
实体类上的注解,这意味着jpa生成的updatesql将只访问更改的列。以上信息不足以在您的情况下正确使用jpa。如果选择jpa,则必须在
object
是的。为了处理这500条记录unique
必须由以下条件之一定义:主键
唯一约束
我建议您使用第二个,因为主键用于在数据库级别标记unique。然后,使用jpa,您应该在数据库中找到新的500条记录中存在的数据,更新它们的修改列,使用
saveAll()
更新它们。然后处理左边的部分,构建实体并使用saveAll()
插入它们。你可能已经注意到
compare and update then save operation in memory
我上面使用的方法不是原子的,可能会导致ConstraintViolationException
插入重复数据时,有两种处理方法:如果数据不是那么严重,您可以只执行上述操作,但为异常的发生保留一些空间,您可以记录信息以进行手动修复,也可以不执行任何操作。但是记住捕获异常,不要使更新操作回滚。
如果您确实对数据很认真,那么可以使用
synchronized
关键字或分布式锁。老实说,我对批处理upsert上的jpa不满意,它不原子,不安全,也不快。我认为这是因为没有一个通用的
upsert
模式,从而orm部分放弃了该功能。我真诚地推荐你使用upsert
使用系统选择的数据库实现的原始sql操作,如mysql insert。。。重复键更新语句。示例代码如下: