Я использую Hibernate JPA и пытаюсь обновить вложенную сущность.
Сущности:
@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;
}
Обновление сущности профиля с помощью новой сущности адреса
@Transactional
@Modifying
@Query("update ProfileEntity set officeAddress=:address where userId=:userId")
int updateProfile(
@Param("userId") Long userId,
@Param("address") AddressEntity address);
Ошибка :
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)
.
.
.
.
Я понимаю, что транзакция не фиксируется после вставки нового AddressEntity, а hibernate сбрасывается перед фиксацией. Таким образом, он не может выполнить обновление ProfileEntity с новым адресом PK.
Но как это исправить?
Я также попытался вставить новый AddressEntity и после фиксации транзакции обновить ProfileEntity, это работает. Но это не очень хорошая практика, потому что, если обновление ProfileEntity вызывает исключение, вставка AddressEntity также должна быть отменена.