java - 来自 JpaRepository 的 saveAll 的唯一约束
问题描述
我的应用程序接收包含对象的数组,这些对象映射到实体然后持久化。
该对象有一个 id 属性,该属性映射到具有唯一约束的列。具有重复 ID 的对象可能会被发送到应用程序。
我正在使用该saveAll
方法,但如果任何对象碰巧违反了唯一约束,它会在插入过程中抛出。
有没有一种简单的方法可以让它插入所有非重复项并忽略重复项,或者只是更新它们?
我尝试过覆盖哈希和等于,但这没有帮助。
该应用程序每秒接收数十个请求,而我希望接收的重复请求数量很少。
实体:
@Table(name = "table", uniqueConstraints = @UniqueConstraint(columnNames = "natural_id"))
public class Entity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "natural_id", unique = true)
private String naturalId;
// ...
}
存储库:
public interface Repository extends JpaRepository<Entity, Long>, JpaSpecificationExecutor<Entity> {}
保存方法:
void save(List<Entities> entities) {
try {
repository.saveAll(entities);
} catch (Exception e) {
log.error("...");
throw e;
}
}
如果我要将保存方法更改为:
@Transactional
void save(List<Entities> entities) {
for (Entities et: entities) {
try {
repository.save(et);
} catch (Exception e) {
log.error("...");
}
}
}
这会让这一切发生在一次交易中吗?我很担心,因为 save 方法通常在每次调用它时都会创建一个新事务,这对于每秒接收相当数量请求的应用程序来说会变得非常慢。
我最终可能必须在插入之前查询数据库以过滤出重复项以进行插入,并在每次捕获到约束违反异常时再次执行此操作。它应该可以工作,但是很丑陋。
解决方案
您必须保存单个记录,因为如果遇到某些记录的问题,则全部保存将不会恢复/恢复,然后其他记录也不会保存,因为所有记录都在同一个事务中。
正如您建议的那样,在插入之前查询数据库以过滤掉重复项,而不是像您提到的“每秒数十个请求”那样使用 try catch 更好地尝试循环,因此它不会产生太多开销。
推荐阅读
- regex - 用不在括号内的逗号分隔?
- lisp - AutoCAD LISP 创建
- angular - Angular Highcharts 中的日期类型 xAxis 仍然允许重复的“日期”值
- python - 当我使用 MITSceneParsing 数据实现 FCN 时,出现此错误 [TypeError: 'NoneType' object is not subscriptable]
- python - 过滤到文本文件后保存列表输出
- javascript - 我在 MEAN 堆栈中的 To Do App 开发需要帮助
- heroku - 无法在 Heroku 上安排备份?
- gitlab - GitLab.com(代码)和托管 GitLab 服务器(Wiki/Issues/CI/CD)之间的集成
- javascript - 单击几下后如何禁用按钮功能?
- halide - 是否可以为卤化物管道创建具有预定义大小的 ImageParam?