Как заставить JpaRepository сохранять только те идентификаторы, которые еще не существуют? - PullRequest
0 голосов
/ 13 марта 2019

С учетом таблицы:

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))
    }
}

Намерение состоит в том, чтобы сохранять метку времени для идентификатора только при первом его появлении.

Приведенный выше код работает, но в моем случае используется более 100 save транзакций в секунду, что ставитбольшая нагрузка на БД.Поэтому я хотел бы оптимизировать, накапливать партию Thing с, а затем использовать что-то вроде saveAll, чтобы иметь все в одной транзакции.

Простое использование saveAll однако также перезапишет временные меткиИдентификаторы уже присутствуют в таблице, которая не предназначена.

Как это можно решить, в идеале, без слишком большого количества низкоуровневого кода?

1 Ответ

1 голос
/ 13 марта 2019

Если вы поместите вышеуказанный цикл в метод @Transactional, у вас должна быть только 1 транзакция - с большим количеством INSERT-ов и SELECT-ов, конечно, но с 1-й транзакцией.Это уменьшит нагрузку на БД.

Кроме того, save () является правильным методом для вызова в этом случае.Существует также метод с именем saveAndFlush (), который противоположен тому, что вы хотите.

Вы также можете ограничить количество SELECT, выполнив repo.findAllById () вместо множества findById ().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...