Детализированный объект Spring-Data на дочернем объекте

1

Имея следующую тестовую настройку с использованием весенних данных CrudRepository

@Test
public void testCreateEventsThatShareALocation() {
    createFirstPlannedEvent();
    createSecondPlannedEvent();
}

@Transactional
private void createSecondPlannedEvent() {
    PlannedEvent plannedEvent = new PlannedEvent();
    Location location = locationRepository.findByName(LOCATION_NAME);
    plannedEvent.setLocation(location);
    plannedEventRepository.save(plannedEvent);
}

@Transactional
public void createFirstPlannedEvent() {
    PlannedEvent plannedEvent = new PlannedEvent();
    Location location = createLocation(LOCATION_NAME); 
    plannedEvent.setLocation(location);
    plannedEventRepository.save(plannedEvent);
}

public Location createLocation(String name) {
    Location location = new Location();
    location.setName(name);
    location.setSomeOtherStuff....(); // Does NOT call the repository save method of Location (there is no repository for Location)
    return location;
}

Когда я запускаю этот тест, я получаю, когда пытаюсь сохранить второй PlannedEvent:

Caused by: org.hibernate.PersistentObjectException: detached entity passed to persist: com.eventage.entities.Location

Когда я отлаживаю код, я замечаю, что первое создание PlannedEvent идет нормально, но оно не работает во втором.

Там в методе сохранения SimpleJpaRepository

entityInformation.isNew(entity) 

вернет true и выкинет вышеописанное исключение при попытке сохранить второй объект.

Тот факт, что он видит объект как новый, является нормальным, поскольку его значение id равно null.

Я не понимаю, как можно отделить местоположение, так как я извлекаю его, прежде чем передать его в PlannedEvent?

Может быть, потому, что и locationRepository, и планируемыйEventRepositor используют другой экземпляр entityManager?

Когда я нарушаю метод сохранения и вызываю.merge вместо.perist, он сохраняет второй PlannedEvent красиво, почему?

Теги:
spring
jpa
spring-data-jpa
spring-data

1 ответ

1
Лучший ответ

Несмотря на то, что ваши методы аннотируются с Transactional, это не так.

Весенние транзакции основаны на прокси. Это означает, что Spring перехватывает вызовы от одного Spring bean к другому Spring bean, благодаря прокси, и запускает/совершает транзакцию, этот другой метод bean-транзакции является транзакционным.

Spring не может перехватывать вызовы метода с одного объекта на этот же объект. Таким образом, у вас действительно есть одна транзакция для каждого звонка в ваши репозитории. Вот почему ваше местоположение отключено.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню