It seems you are encountering a TransientObjectException when upgrading your Hibernate version from 6.5.2 to 6.6.29. The error indicates that a persistent instance is referencing an unsaved transient instance of DummyResource. Here’s a reformatted version of your problem description and code, along with some thoughts on how to address the issue.
the same code is working fine in 6.5.2 version
When attempting to post using the updated Hibernate version (6.6.29), an exception occurs:
org.springframework.dao.InvalidDataAccessApiUsageException:
org.hibernate.TransientObjectException: persistent instance references an unsaved transient instance of 'com.xxx.xxx.service.entity.DummyResource'
(save the transient instance before flushing)
Caused by: org.hibernate.TransientObjectException:
persistent instance references an unsaved transient instance of 'com.xxx.xxx.service.entity.DummyResource'
(save the transient instance before flushing)
Code Snippet
Here’s the relevant code where the issue occurs:
public void saveDummyWebAndChildElements(final DummyWeb dummyWeb) {
this.saveDummyWeb(dummyWeb);
updateParentReferenceAndSaveEntity(dummyWeb, dummyWeb.getDummyWebResources(), "dummyWeb", dummyWebResourceRepository);
for (DummyWebResource dummyWebResource : dummyWeb.getDummyWebResources()) {
updateParentReferenceAndSaveEntity(dummyWebResource, dummyWebResource.getDummyResourceItems(), "dummyWebResource", dummyWebResourceItemRepository);
}
updateParentReferenceAndSaveEntity(dummyWeb, dummyWeb.getDummyValves(), "dummyWeb", dummyValveRepository);
for (DummyValve dummyValve : dummyWeb.getDummyValves()) {
updateParentReferenceAndSaveEntity(dummyValve, dummyValve.getDummyValveAdditives(), "dummyValve", dummyValveAdditiveRepository);
updateParentReferenceAndSaveEntity(dummyValve, dummyValve.getDummyValveFuels(), "dummyValve", dummyValveFuelRepository);
}
dummyWebRepository.flush();
}
protected <T, S> void updateParentReferenceAndSaveEntity(final T parentEntity, final List<S> childEntityList, final String attrName,
@SuppressWarnings("rawtypes") final JpaRepository jpaRepository) {
if (CollectionUtils.isEmpty(childEntityList)) {
return;
}
childEntityList.forEach(childEntity -> {
BeanWrapper trgWrap = PropertyAccessorFactory.forBeanPropertyAccess(childEntity);
trgWrap.setPropertyValue(attrName, parentEntity);
});
if (CollectionUtils.isNotEmpty(childEntityList)) {
jpaRepository.saveAll(childEntityList);
}
}
Entity Classes
Here are the relevant entity classes that are part of this setup:
DummyWeb.java
@Entity
@Table(name = "DUMMY_WEB")
@AttributeOverride(name = "id", column = @Column(name = "DUMMY_ID"))
@AttributeOverride(name = "createdDate", column = @Column(name = "DATE_CREATED"))
@AttributeOverride(name = "lastUpdated", column = @Column(name = "DATE_MODIFIED"))
@Getter
@Setter
@ToString(callSuper = true)
public class DummyWeb extends DummyBaseEntity implements Serializable {
private static final long serialVersionUID = 1L;
@Transient
private String dummyType;
@Transient
private boolean canDoSomething;
@OneToOne(mappedBy = "dummyWeb", orphanRemoval = true, fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private DummyAddress dummyAddress;
@Transient
private List<DummyResource> dummyResources;
@Transient
private List<DummyValve> dummyValves;
@PrePersist
@PreUpdate
public void prePersistOrPreUpdate() {
if (dummyAddress != null) {
dummyAddress.setDummyWeb(this);
}
}
}
DummyResource.java
@Entity
@Table(name = "DUMMY_RESOURCE")
@AttributeOverride(name = "id", column = @Column(name = "DUMMY_RESOURCE_ID"))
@Getter
@Setter
@ToString(callSuper = true, exclude = "dummyWeb")
public class DummyResource extends DummyBaseEntity implements Serializable {
private static final long serialVersionUID = 1L;
@Column(name = "DUMMY_RESOURCE_CODE", length = 75, nullable = false)
private String dummyResourceCode;
@Column(name = "DUMMY_END_TIME")
@Temporal(TemporalType.TIMESTAMP)
private Date dummyEndTime;
@ManyToOne
@JoinColumn(name = "DUMMY_WEB_ID", referencedColumnName = "DUMMY_WEB_ID", nullable = false)
private DummyWeb dummyWeb;
}
DummyValve.java
@Entity
@Table(name = "DUMMY_VALVE")
@AttributeOverride(name = "id", column = @Column(name = "DUMMY_VALVE_ID"))
@Getter
@Setter
@ToString(callSuper = true, exclude = "dummyWeb")
public class DummyValve extends DummyBaseEntity implements Serializable {
private static final long serialVersionUID = 1L;
@ManyToOne
@JoinColumn(name = "DUMMY_WEB_ID", referencedColumnName = "DUMMY_WEB_ID", nullable = false)
private DummyWeb dummyWeb;
@Column(name = "DUMMY_VALVE_NUMBER", nullable = false)
private Integer dummyValveNumber;
@Column(name = "DUMMY_SERVICE_LEVEL_CODE", length = 40)
private String dummyServiceLevelCode;
}