Является ли CrudRepository.save(Iterable<S>) атомарным?

Я сохраняю несколько объектов, используя CrudRepository.save(Iterable<S>).

Является ли это поведение операции атомарным?

Что произойдет, если я сохраню 10 объектов, а для 6-го не получится?

Все методы IIRC из CrudRepository по умолчанию получат аннотацию @Transactional, поэтому сбой ничего не сохранит в БД.

Eugene 27.05.2019 12:39
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
1
2 089
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Да, это атомарно. SimpleJpaRepository — это реализация по умолчанию для интерфейса CrudRepository. Метод save помечен Transactional при реализации. Так что в случае какой-либо ошибки все будет откатываться.

@Transactional
public <S extends T> List<S> save(Iterable<S> entities) {
    List<S> result = new ArrayList();
    if (entities == null) {
        return result;
    } else {
        Iterator var3 = entities.iterator();

        while(var3.hasNext()) {
            S entity = var3.next();
            result.add(this.save(entity));
        }

        return result;
    }
}
Что произойдет, если я сохраню 10 объектов, а для 6-го не получится? и вы отвечаете "Да"?
Eugene 27.05.2019 12:42

@ Юджин, я думаю, он имел в виду: Yes, it is atomic. Что в этом плохого ?

NiVeR 27.05.2019 12:43

@NiVeR ничего плохого если он это имел в виду ... и в таком случае потребуется правильное редактирование

Eugene 27.05.2019 12:44

Евгений и NiveR, Спасибо за отзыв. Я отредактировал свой ответ.

samzz 27.05.2019 13:26

Согласно документация, вот как выглядит saveAll:

@Transactional
public <S extends T> List<S> saveAll(Iterable<S> entities)

Но чтобы быть уверенным, что это будет работать как одна атомарная транзакция, вам нужно:

1) Убедитесь, что транзакции поддерживают работу на вас

2) Убедитесь, что для autocommit установлено значение false (необязательно, если не сработает)

Spring отключает автофиксацию для методов @Transactional (когда такой метод выполняется и возвращается к предыдущей настройке после завершения), поэтому пункт 2 не нужен.

Lesiak 27.05.2019 12:44

@Lesiak Раньше у меня были проблемы с autocomit=true + Spring Boot 1.5 + MariaDB. На самом деле это не работало как отдельная атомарная транзакция, прежде чем я отправил autocommit + autocommit по умолчанию на false. Добавьте необязательную метку к # 2, спасибо

alexey28 27.05.2019 12:51
Ответ принят как подходящий

За увиденным вот что происходит в случае SimpleJpaRepository метода сохранения с помощью Iterable

@Transactional
public <S extends T> List<S> More save(Iterable<S> entities) {

    List<S> result = new ArrayList<S>();

    if (entities == null) {
        return result;
    }

    for (S entity : entities) {
        result.add(save(entity));
    }

    return result;
}

Стоит отметить, что сохранение с Iterable изменилось на saveAll в последних версиях. См. изменения для более подробной информации

What will happen if I save 10 entities and it fails for 6th one?

По умолчанию CrudRespository будет иметь @Transactional, поэтому в случае исключения ничего не сохраняется.

В случае обработки вручную это будет работать

Если вы делаете что-то подобное, это будет откат.

@Transactional(rollbackFor=RuntimeException.class)
public List<Car> saveAllOrNone(List<Car> cars) {
    for(Car car: cars) {
        repo.save(car);
    }
}

Другие вопросы по теме