Существует ли простой способ использовать предоставленные идентификаторы для сущностей при сохранении их в пустую базу данных?
При использовании EntityManager.persist(...)
вызов завершается неудачно, так как он думает, что объект отключен (так как у него есть идентификатор),Я не хочу использовать EntityManager.merge(...)
по соображениям производительности (он запускает дополнительный выбор для каждой сущности).
Я пробовал разные способы, например, предоставление ForeignGenerator
, но идентификаторы обнуляются перед сохранением и NPE
Я также пытался предоставить Hibernate Interceptor
и переопределить его isTransient()
, чтобы всегда возвращать true
, но тогда я не могу правильно сохранить каскадное сохранение (или, по крайней мере, я должен поддерживать кэшя уже сохранил сущности).
Я думаю, что должен быть простой способ сделать это, но не могу найти какой-либо.
Обновлено: добавлены сопоставления сущностей
@Entity
@Data
@NoArgsConstructor
@EqualsAndHashCode(of = "admNr")
public class Adm implements Serializable {
@Id
@Column(name = "ADM_NR", nullable = false)
private String admNr;
@OneToMany(mappedBy = "adm", cascade = CascadeType.ALL)
private Set<Kunde> kundeList = new HashSet<>();
}
@Entity
@Data
@NoArgsConstructor
@EqualsAndHashCode(of = "kundeNr")
public class Kunde implements Serializable {
@Id
@Column(name = "Kunde_Nr", nullable = false)
private String kundeNr;
@ManyToOne(optional = false)
@JoinColumn(name = "ADM_Nr", referencedColumnName = "ADM_NR")
private Adm adm;
}
Обновлено: предоставлено дополнительная информация
Я не создаю объекты вручную, они создаются как часть процедуры переноса данных, и правильно устанавливаются двунаправленные отношенияв процессе, так что это не возможно, что kunde.getAdm()
когда-либо будет нулевым.В любом случае, я попытался удалить nullable = false
из Kunde.adm
, но результат был тот же.
Я настроил каскады, чтобы иметь возможность сохранять весь график, используя em.persist(adm)
, как я не хотелпосещайте каждого ребенка и сохраняйте его в явном виде (модель, которую я предоставил, является упрощенной, на самом деле в ней больше уровней вложенности).
String
PK - это устаревшие вещи, от которых, к сожалению, я не могу избавиться.
Ошибка, возникающая при сохранении графика (вызов em.persist(adm)
):
java.lang.IllegalStateException: org.hibernate.TransientPropertyValueException: Not-null property references a transient value - transient instance must be saved before current operation : de.apollon.dmx.workflow.processing.sqlite.adm.domain.Kunde.adm -> de.apollon.dmx.workflow.processing.sqlite.adm.domain.Adm
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:146) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:157) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:164) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:797) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:768) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:564) ~[na:na]
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:305) ~[spring-orm-5.0.8.RELEASE.jar:5.0.8.RELEASE]
at com.sun.proxy.$Proxy129.persist(Unknown Source) ~[na:na]
at de.apollon.dmx.workflow.processing.sqlite.adm.service.SqliteAdmPackageService.storeAdmPackage(SqliteAdmPackageService.java:60) ~[classes/:na]
at de.apollon.dmx.workflow.processing.sqlite.adm.service.SqliteAdmPackageService.createAdmPackageResource(SqliteAdmPackageService.java:48) ~[classes/:na]
at de.apollon.dmx.workflow.processing.sqlite.adm.service.SqliteAdmPackageService$$FastClassBySpringCGLIB$$6a54d95.invoke(<generated>) ~[classes/:na]
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) ~[spring-core-5.0.8.RELEASE.jar:5.0.8.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:746) ~[spring-aop-5.0.8.RELEASE.jar:5.0.8.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.0.8.RELEASE.jar:5.0.8.RELEASE]
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:294) ~[spring-tx-5.0.8.RELEASE.jar:5.0.8.RELEASE]
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98) ~[spring-tx-5.0.8.RELEASE.jar:5.0.8.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.8.RELEASE.jar:5.0.8.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688) ~[spring-aop-5.0.8.RELEASE.jar:5.0.8.RELEASE]
at de.apollon.dmx.workflow.processing.sqlite.adm.service.SqliteAdmPackageService$$EnhancerBySpringCGLIB$$5ba50508.createAdmPackageResource(<generated>) ~[classes/:na]
at de.apollon.dmx.workflow.processing.service.AdmPackageService.createAdmPackage(AdmPackageService.java:59) ~[classes/:na]
at de.apollon.dmx.workflow.processing.service.ProcessingService.processAdmPackage(ProcessingService.java:111) [classes/:na]
at de.apollon.dmx.workflow.processing.service.ProcessingService.runTest(ProcessingService.java:58) [classes/:na]
at de.apollon.dmx.workflow.Application.lambda$applicationRunner$0(Application.java:31) [classes/:na]
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:514) ~[na:na]
at java.base/java.util.concurrent.FutureTask.runAndReset$$$capture(FutureTask.java:305) ~[na:na]
at java.base/java.util.concurrent.FutureTask.runAndReset(FutureTask.java) ~[na:na]
at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:305) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1135) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) ~[na:na]
at java.base/java.lang.Thread.run(Thread.java:844) ~[na:na]
Caused by: org.hibernate.TransientPropertyValueException: Not-null property references a transient value - transient instance must be saved before current operation : de.apollon.dmx.workflow.processing.sqlite.adm.domain.Kunde.adm -> de.apollon.dmx.workflow.processing.sqlite.adm.domain.Adm
at org.hibernate.action.internal.UnresolvedEntityInsertActions.checkNoUnresolvedActionsAfterOperation(UnresolvedEntityInsertActions.java:122) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.engine.spi.ActionQueue.checkNoUnresolvedActionsAfterOperation(ActionQueue.java:432) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.internal.SessionImpl.checkNoUnresolvedActionsAfterOperation(SessionImpl.java:631) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:794) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
... 29 common frames omitted