Весенний ботинок. Выполнение saveAndFlush с изменением объекта приводит к несохраненному переходному исключению

У меня есть сложная сущность:

public class Task {
   @OneToOne(orphanRemoval=true, mappedBy = "parent")
   @Cascade(value = CascadeType.ALL) (org.hibernate.annotations ... package)
   private Executor executor;
...
}

public class Executor {
   @OneToOne
   @JoinColumn
   private Task parent;

   @ManyToOne
   @Cascade(value = CascadeType.ALL)
   private List<Property> propList = new LinkedList<Property>();
}

Как правило, это «Задача», которая формирует «Исполнителя», а «Исполнитель» заполняется некоторыми специфическими свойствами.

Если я делаю это обычным образом, то есть:

@Service
public class Service {
   @PostConstruct
   private void test() {
      Task task = new Task();
      Executor ex = new Executor();
      List<Property> props = ex.getProperties();
      ... forming and adding some properties
      taskDao.saveAndFlush(task);
   }

Все в порядке, и задача сохраняется правильно.

Но так как это упрощено, и мне нужно сохранить Task в тот момент, когда я его получу, то есть сразу после определения, и сохранить его (сброс, без сброса, разделение на отдельный метод с транзакцией),

@Service
public class Service {
   @PostConstruct
   private void test() {
      Task task = new Task();
      taskDao.saveAndFlush(task); // no change in the exception if I properly move this out to a separate method with @Transactional
      Executor ex = new Executor();
      List<Property> props = ex.getProperties();
      ... forming and adding some properties
      taskDao.saveAndFlush(task);
   }

Я получаю «несохраненную транзакцию», которая указывает на вторую «saveAndFlush».

И это достижимо только в том случае, если я заполню Свойства, что означает, что закомментировав часть «свойства формирования», все работает хорошо.

Каскад ВСЕ (полный список, хранящийся в org.hibernate.annotations...), поэтому у меня есть сомнения, что я забыл указать «Каскад».

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

Ответы 1

Ответ принят как подходящий

saveAndflush не переводит объект в управляемое состояние, вам необходимо использовать управляемый объект, возвращаемый этим методом. Попробуйте это решение:

@PostConstruct
private void test() {
   Task task = new Task();
   task = taskDao.saveAndFlush(task);  // reassign
   Executor ex = new Executor();
   List<Property> props = ex.getProperties();
   ... forming and adding some properties
   taskDao.saveAndFlush(task);
}

БД - это MySQL, а @OneToMany(cascade = CascadeType.ALL) не распространяется на "CascadeType.REMOVE", что затрудняет каскадное удаление дочерних элементов.

Draaksward 17.04.2019 16:44

Не говорите мне, что я застрял между удалением детей и «всеми остальными» вещами :)

Draaksward 17.04.2019 16:46

Это все, что приходит мне в голову, попробуйте, и я постараюсь придумать что-нибудь получше, чем это ;)

Andronicus 17.04.2019 16:47

Да, этот я тоже пробовал несколько раз. Даже при сохранении применялся избыточный подход, затем выборка сохраненного элемента по сформированному идентификатору, а затем повторная попытка (даже с отдельным методом для сохранения и возврата, который запрашивал сущность по сформированному идентификатору.

Draaksward 18.04.2019 09:19

Что ж, я только что попробовал это на другом наборе сущностей, и оказалось, что проблема каким-то образом заключается в текущих сущностях, которые я использую (которые немного запутаны с точки зрения DDL).

Draaksward 18.04.2019 09:52

Да, еще раз ошибкой было определение объекта (таблица позади объекта была разработана... кем-то случайным образом). Неправильное определение в определении свойства, относящееся к родительскому объекту. Исправил и все пошло хорошо.

Draaksward 18.04.2019 10:43

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