如何使JpaRepository仅保存尚不存在的ID?

时间:2019-03-13 14:42:39

标签: spring-boot kotlin spring-data-jpa

提供表格:

CREATE TABLE mytable (
    some_id      BIGINT PRIMARY KEY NOT NULL,
    timestamp    TIMESTAMP WITH TIME ZONE NOT NULL
);

实体:

@Entity
@Table(name = "mytable")
class Thing(
        @Id
        var some_id: Long,
        var timestamp = ZonedDateTime.now()
)

存储库:

interface MyRepo : JpaRepository<Thing, Long>

这个循环:

val myRepo: MyRepo

while (True) {
    val some_id: Long = ComesFromSomewhere()
    if (myRepo.findById(some_id) == null) {
        myRepo.save(Thing(some_id))
    }
}

目的是仅在ID首次出现时为该ID存储时间戳。

上面的代码可以工作,但是在我的用例中每秒导致超过100 save个事务,这给数据库带来了沉重的负担。因此,我想进行优化,累积一批Thing,然后使用类似saveAll的东西在一次交易中完成所有操作。

不过,仅使用saveAll也会覆盖表中已经存在的ID的时间戳,这不是故意的。

在没有太多低级代码的情况下如何解决?

1 个答案:

答案 0 :(得分:1)

如果将上述循环放在@Transactional方法中,则应该只有1个事务-当然,有很多INSERT和SELECT-事务,但是只有1个事务。这将减轻数据库的负担。

此外,在这种情况下,save()是调用的正确方法。还有一种名为saveAndFlush()的方法,与您想要的相反。

您还可以通过执行repo.findAllById()而不是很多findById()来限制SELECT的数量。