Отсоединение сохраненной родительской сущности при сохранении однонаправленной дочерней сущности «один к одному» - PullRequest
0 голосов
/ 04 сентября 2018

Я пишу несколько тестов для моего первого приложения с использованием весенней загрузки. Я создал однонаправленное отношение между пользователем и учителем, используя @MapsId, так что pks пользователя и учителя совпадают. Теперь я думаю, что, поскольку отношение указано только для части учителя, пользователь не будет сохранен при вызове операции сохранения. Хотя каким-то образом при сохранении учителя (новой сущности) с подключенным пользователем (сохраняется в базе данных) я получаю исключение отсоединенной сущности. Соответствующая часть сущности выглядит так:

@Entity
public class Teacher {

    @Id
    private Long id;

    @OneToOne(fetch = FetchType.LAZY)
    @MapsId
    private User user;

}

А пользовательский объект не имеет ссылки на класс учителя:

@Entity
public class User {
// some fields getters and setters
}

В моем тесте я сначала создаю пользователя:

@Test doSomeUserOperations() {
    User user = new User()
    // set some user info
    userRepository.save(user)

    // next i want to couple a teacher entity via a method in the teacher service
    Teacher teacher = teacherService.getAndCreateTeacherForUser(user.getId());
}

С учителем службы выглядит следующим образом:

@Service
public class TeacherService {
    @Autowired TeacherRepository teacherRepo; (both extending JpaRepo)
    @Autowired UserRepository userRepo;

    public Teacher getAndCreateTeacherForUser(Long userId) {
        Teacher newTeacher = new Teacher();

        newTeacher.setUser(userRepo.findById(userId).get());

        return teacherRepo.save(newTeacher);
    }

}

Теперь в обратной строке я получаю следующую трассировку исключений:

org.springframework.dao.InvalidDataAccessApiUsageException: detached entity passed to persist: com.dorresteijn.wordteacher.model.User; nested exception is org.hibernate.PersistentObjectException: detached entity passed to persist: com.dorresteijn.wordteacher.model.User
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:280)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:225)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:527)
at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61)
at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:242)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:153)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:135)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:61)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
at com.sun.proxy.$Proxy154.save(Unknown Source)
at 

Ответы [ 2 ]

0 голосов
/ 04 сентября 2018

Это может быть проблемой логики слияния, я думаю, что в этом случае save используется для создания новых объектов, и он будет жаловаться, если в иерархии уже сохранено object. Вы должны использовать saveOrUpdate в таких случаях вместо save.

0 голосов
/ 04 сентября 2018

Ответ очень прост. Ваш сервис не является транзакционным, и из-за этого чтение Пользователя происходит в другой транзакции, чем постоянное чтение учителя. Между чтением и записью это отделяется. Поместите одну аннотацию @Transactional сверху или убедитесь, что она работает, и она будет работать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...