问题: 控制台save the transient instance before flushing,object references an unsaved transient instance
org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing :Data ->Data; nested exception is java.lang.IllegalStateException: org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing : at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:371) at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:257) at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:538) at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:743) at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:711) at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:633) at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:386) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:118) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor . CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:178)atorg.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)atorg.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:95)atorg.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)atorg.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)atcom.sun.proxy.Proxy172.save(Unknown Source) at serial.ReadThread.run(ReadThread.java:57) Caused by: java.lang.IllegalStateException: org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing : at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:151) at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:181) at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:188) at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1366) at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:453) at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:3212) at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2380) at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:448) at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:183) at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access 300(JdbcResourceLocalTransactionCoordinatorImpl.java:40)atorg.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImplTransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:281) at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:101) at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:534) ... 17 more Caused by: org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing : com.test.Data at org.hibernate.engine.spi.CascadingActions$8.noCascade(CascadingActions.java:379) at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:169) at org.hibernate.event.internal.AbstractFlushingEventListener.cascadeOnFlush(AbstractFlushingEventListener.java:159) at org.hibernate.event.internal.AbstractFlushingEventListener.prepareEntityFlushes(AbstractFlushingEventListener.java:149) at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:82) at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39) at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:99) at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1362) ... 26 more
解决方案
这个异常堆栈信息显示了在Spring Data JPA与Hibernate配合使用时遇到的一个常见问题,即尝试在持久化实体时,它关联的属性是一个未被保存的瞬态实例。根据Hibernate的工作机制,在flush操作期间,如果发现一个持久化实体引用了未经持久化的关联对象,就会抛出TransientPropertyValueException异常。
解决这个问题的方法如下:
1、在调用.save之前,确保先保存或更新其关联的实例:
// 假设有个实体 Test1 test= ... // 创建或获取test1实例 testService.save(test); // 先保存DeviceData Test2 test2= test2.setLastData(test.testId); test2Service.save(cntrnum); // 现在可以安全地保存Cntrnum
2、如果实体之间存在级联关系(Cascade),并且你应该在保存Cntrnumber时自动保存DeviceData,请检查你的实体类中对应的@ManyToOne或@OneToOne注解是否配置了正确的cascade策略,如CascadeType.PERSIST或CascadeType.ALL。
@Entity public class Test1{ @ManyToOne(cascade = CascadeType.ALL) private Test2 test2 ; // ... }