#java #spring-boot #hibernate #transactions #spring-transactions
Вопрос:
У меня есть метод, который вызывает 3 дочерних метода перед совершением транзакции с репозиторием, например :
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Service
public class ObjectService {
@Transactional
public void doSomething() {
objectRepository.findAllObject();
childMethod1();
childMethod2();
childMethod3();
objectRepository.save(int id);
}
public void childMethod1() {
//do something
}
public void childMethod2() {
//do something
}
public void childMethod3() {
//do something
}
}
и в репозитории есть метод выбора и сохранения :
@Query("SELECT * FROM object WHERE id is null")
Optional<Obeject> findAllObject();
@Query("SELECT * FROM object WHERE id is null")
Optional<Obeject> save(int id);
В моем случае, если я использую эту систему в таблице со 100 тысячами записей, приложение запускается с выполнения запросов quicl, но транзакция не выполняется (нет перемещения в базе данных), потому что программа, похоже, ожидает выполнения всей работы перед выполнением метода репозитория.
Таким образом, на самом деле, если я использую этот метод для всех записей таблицы, загрузка Spring будет становиться все меньше и меньше и завершится блокировкой без внесения ни одного изменения в базу данных.
Так что, на самом деле, я создал конечную точку для этого с циклом из 1000 элементов. Просто нужно пропинговать его с помощью задания bash, и это работает, но это грязный метод.
Я хотел бы знать, какова наилучшая практика и является ли этот второй способ хорошим методом для вас :
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Service
public class ObjectService {
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void doSomething() {
objectRepository.findAllObject();
childMethod1();
childMethod2();
childMethod3();
objectRepository.save(int id);
}
public void childMethod1() {
//do something
}
public void childMethod2() {
//do something
}
public void childMethod3() {
//do something
}
}
Если я правильно понимаю, аннотация
@Транзакционный(распространение = Распространение.REQUIRES_NEW)
будет ли выполнена 1 транзакция в конце выполнения родительского метода для всех объектов, возвращаемых репозиторием, вместо ожидания окончания выполнения для всего объекта, верно?
Извините, если эти вопросы кажутся вам простыми, я пытаюсь понять документацию, но ее трудно понять с плохим уровнем английского языка.
Спасибо за вашу помощь!
ИЗМЕНИТЬ: добавить методы репозитория
Комментарии:
1. Пожалуйста, прочитайте: Могу ли я задать только один вопрос за пост?
2. Это был скорее дополнительный вопрос, но, ладно, я его удалил. 🙂
3. » … выполнит 1 транзакцию в конце выполнения » — Нет. Транзакция открывается в начале
@Transactional
метода (через перехватчик) и закрывается при возврате метода. Фиксация происходит, когда метод возвращается (опять же, через перехватчик).4. Хм, это странно, потому что репозиторий ожидает окончания выполнения X-кратного выполнения метода перед записью в базу данных… Возможно ли, что @Transactional совершает фиксацию и ждет окончания всего процесса, чтобы записать их в базу данных с репозиторием?
5. Ах да. Это кое-что объясняет. Таким образом, размер проблемы увеличивается. В этом случае я предполагаю, что транзакция просто «слишком велика» (т. Е. Слишком много строк обновляется). Я бы предложил обрабатывать записи в пакетных размерах. Ваши данные свидетельствуют о том, что размер пакета от 100 до 1000 кажется разумным.