'org.hibernate.PersistentObjectException: detached entity passed to persist:'

'org.hibernate.PersistentObjectException: detached entity passed to persist:'

尝试在我们的 Web 应用程序上创建课程实体实例时出现以下错误。这是一个 JHipster 应用程序完整的错误日志如下,但主要错误是

'org.hibernate.PersistentObjectException: detached entity passed to persist:'

违规代码似乎在此 class:CourseResoure.java

完整代码位于:

https://github.com/smitht06/aseproj

org.springframework.dao.InvalidDataAccessApiUsageException: detached entity passed to persist: edu.uwf.cen6030.domain.User; nested exception is org.hibernate.PersistentObjectException: detached entity passed to persist: edu.uwf.cen6030.domain.User
        at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:319)
        at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:255)
        at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:528)
        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:186)
        at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:178)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
        at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:95)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
        at com.sun.proxy.$Proxy183.save(Unknown Source)
        at edu.uwf.cen6030.web.rest.CourseResource.createCourse(CourseResource.java:68)

更新代码:

    @PostMapping("/courses")
    @Transactional()
    public ResponseEntity<Course> createCourse(@Valid @RequestBody Course course) throws URISyntaxException {
        log.debug("REST request to save Course : {}", course);
        if (course.getId() != null) {
            throw new BadRequestAlertException("A new course cannot already have an ID", ENTITY_NAME, "idexists");
        }
        if (Objects.isNull(course.getTeacher())) {
            throw new BadRequestAlertException("Invalid association value provided", ENTITY_NAME, "null");
        }

        Long userId = course.getTeacher().getId();
        userRepository.findById(userId).ifPresent(course::user);
        Course result = courseRepository.save(course);
        return ResponseEntity.created(new URI("/api/courses/" + result.getId()))
            .headers(HeaderUtil.createEntityCreationAlert(applicationName, false, ENTITY_NAME, result.getId().toString()))
            .body(result);
    }

错误是因为您从教师 ID 加载用户实体,然后将其附加到 user 字段,而它应该附加到教师 ifPresent(course::teacher) 和 [=13] =] class 级别 CourseResource 或方法级别 CourseResource#createCourse() 的注释。

因此,Hibernate 抱怨教师实体尚未加载到 EntityManager(即教师已分离),因为它来自 JSON 请求主体并且仅包含一个 ID。

我必须说,您附加的代码无法与您的 git 存储库中的代码一起编译。

以下修改后的代码通过 CourseResourceIT 单元测试

    @PostMapping("/courses")
    @Transactional
    public ResponseEntity<Course> createCourse(@Valid @RequestBody Course course) throws URISyntaxException {
        log.debug("REST request to save Course : {}", course);
        if (course.getId() != null) {
            throw new BadRequestAlertException("A new course cannot already have an ID", ENTITY_NAME, "idexists");
        }
        if (Objects.isNull(course.getTeacher())) {
            throw new BadRequestAlertException("Invalid association value provided", ENTITY_NAME, "null");
        }
        Long userId = course.getTeacher().getId();
        userRepository.findById(userId).ifPresent(course::teacher);
        Course result = courseRepository.save(course);
        return ResponseEntity.created(new URI("/api/courses/" + result.getId()))
            .headers(HeaderUtil.createEntityCreationAlert(applicationName, false, ENTITY_NAME, result.getId().toString()))
            .body(result);
    }