Различное поведение персистентности с In-Memory и MySQL DB
У меня есть родительский объект и дочерний объект с отношением один ко многим.
При использовании @DataJpaTest (т. Е. При настройке базы данных в памяти) работает следующее:
LOG.info("Creating stops");
Stop stop1 = new Stop(new Time(0), "Acton Town", new HashSet<>());
Set<Stop> stops = new HashSet<>();
stops.add(stop1);
LOG.info("Creating and persisting routes");
Route route = routeRepository.save(new Route("something", "return"));
LOG.info("Adding stops to route");
stops.forEach(route::addStop);
Он правильно вставляет маршрут и каждого потомка, и я могу получить маршрут позже и получить ту же информацию обратно.
Однако, когда я повторяю это в моем сервисе при использовании реального источника данных (локальной базы данных MySQL), персистирование CASCADE.ALL, по-видимому, не происходит, и я в конечном итоге не вставляю остановки, но маршрут сохраняется и назначается. Я БЫ.
Я следовал совету со всего сайта, используя метод "addEntity" в родительском элементе, который настраивал двунаправленные отношения, но он не работает за пределами набора тестов.
Кто-нибудь знает, почему это может быть?
1 ответ
Поэтому одним из различий между моим тестом и моим сервисом было использование entityManager.flush().
Добавляя @Transactional к моему методу обслуживания, дочерние элементы сохраняются, поскольку это оборачивает вызов метода в прокси-сервере AOP, который по существу делает это:
transaction.begin()
service.method()
transaction.commit()
Кажется, что мои дети не были настойчивы, потому что я фактически не говорил спящему, когда делать это.
Причина, по которой я раньше этого не замечал в других сервисах, заключается в том, что я использовал CrudRepository для сохранения сущностей, которые бы сразу же заполняли поле id, так что это по существу зафиксировало бы транзакцию.
На это также может повлиять мультитенантная среда, в которой я работаю, где у меня несколько менеджеров транзакций. Если это так, вам, вероятно, придется указать, какой из них с транзакционной аннотацией выглядит так:
@Transactional("nameoftransactionmanager")