【问题标题】:Unique constraint with saveAll from JpaRepository来自 JpaRepository 的 saveAll 的唯一约束
【发布时间】:2021-07-15 00:09:24
【问题描述】:

我的应用程序接收包含对象的数组,这些对象被映射到实体,然后被持久化。

该对象有一个 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 方法通常在每次调用时都会创建一个新事务,这对于每秒接收大量请求的应用程序来说会变得非常慢。

我最终可能必须在插入之前查询数据库以过滤出重复的插入,并在每次捕获到约束违反异常时再次执行此操作。它应该可以工作,但是很丑。

【问题讨论】:

    标签: java mysql spring-boot hibernate jpa


    【解决方案1】:

    您必须保存单个记录,因为如果某些记录遇到问题,则全部保存将不会恢复/恢复,然后其他记录也不会保存,因为所有记录都在同一事务中。

    正如你所建议的 在插入之前查询数据库以过滤掉重复项而不是那个 最好尝试 for loop with try catch 正如您提到的“每秒数十个请求”,这样它不会产生太多开销。

    【讨论】:

      【解决方案2】:

      如果您已经实现了 hashCode 和 equals,那么在保存之前使用 Set 而不是 List 来收集您的项目。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-11-05
        • 2018-02-02
        • 1970-01-01
        • 2022-07-27
        • 1970-01-01
        • 2011-06-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多