I'm using Hibernate JPA and trying to update nested entity.
Entities:
@Entity
@Table(name = "profile")
@AllArgsConstructor
@NoArgsConstructor
public class ProfileEntity implements Serializable {
........
@OneToOne(cascade = CascadeType.ALL,fetch = FetchType.EAGER)
@JoinColumn(name="office_address")
private AddressEntity officeAddress;
}
@Entity
@Table(name="address")
@AllArgsConstructor
@NoArgsConstructor
public class AddressEntity implements Serializable{
......
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name="user_id")
private ProfileEntity userProfile;
}
Updating Profile entity with new Address entity
@Transactional
@Modifying
@Query("update ProfileEntity set officeAddress=:address where userId=:userId")
int updateProfile(
@Param("userId") Long userId,
@Param("address") AddressEntity address);
Error:
org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.example.entities.AddressEntity; nested exception is java.lang.IllegalStateException: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.example.entities.AddressEntity
at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:381)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:227)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:436)
at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:59)
at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:147)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:133)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
.
.
.
.
I understand as the transaction is not committed after a new AddressEntity is inserted, and hibernate is flushing before committing. Thus, it's unable to make an update to ProfileEntity with the new address PK.
But how to fix it ?
I also tried inserting a new AddressEntity and after committing the transaction, updating ProfileEntity, that works. But that's not a good practice, because if ProfileEntity update throws an exception AddressEntity insert should also be rolled back.