保存单向一对一子实体时分离的固定的父实体

时间:2018-09-04 13:34:15

标签: java hibernate jpa

我正在使用Spring Boot为我的第一个应用程序编写一些测试。我使用@MapsId在用户和教师之间创建了单向关系,以便用户和教师的pk相同。现在,我认为由于该关系仅在教师部分指定,因此在调用保存操作时不会保存用户。虽然以某种方式在与耦合用户(持久存储在数据库中)保存教师(新实体)时出现了分离的实体异常。实体的相关部分如下:

@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());
}

teacherService的外观如下:

@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 :(得分:1)

答案很简单。您的服务不是事务性的,因此,用户的阅读与老师的坚持是不同的事务。在读取和写入之间,它被分离。在顶部放一个@Transactional批注或手动确保交易能力,它将起作用。

答案 1 :(得分:0)

这可能是合并逻辑的问题,我认为在这种情况下,save用于创建新对象,如果层次结构中已经保存了object,它会发出抱怨。在这种情况下,您应该使用saveOrUpdate,而不是save