使用 PostgreSQL 时,一对一关联在 5.4.0+ 上产生错误

2024-03-03

我们有使用 OneToOne 注释和 PostgreSQL 的 Spring Boot 应用程序。

所属类别:

@Table(name = "PAYMENT")
public class PaymentDO  {

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Column(name = "PAYMENT_ID", insertable = false, updatable = false, nullable = false)
  private Long paymentId;

  @OneToOne(mappedBy = "payment", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
  private PaymentBatchJobDO paymentBatchJob;

}

所属类别:

@Table(name = "PAYMENT_BATCH_JOB")
public class PaymentBatchJobDO {

  @Id
  @Column(name="PAYMENT_ID", updatable = false, nullable = false)
  private Long paymentId;

  @OneToOne
  @PrimaryKeyJoinColumn(name = "PAYMENT_ID", referencedColumnName = "PAYMENT_ID")
  private PaymentDO payment;

}

我想要做的是保存一个 PaymentDO,然后向其中添加一个 PaymentBatchJobDO(使用 Spring 的 JpaRepository)。奇怪的是,当尝试保存 PaymentBatchJobDO 时,此操作失败了。

PaymentBatchJobDO 是 PaymentDO 的可选子项。该关系是使用“共享主键”完成的。这意味着 PaymentBatchJobDO 的 paymentId 字段的值与 PaymentDO 的 paymentId 字段的值相同。

直到 Hibernate core 5.3.* 工作完美,但使用 5.4.* 我收到以下错误:

2020-02-14 11:08:20.631  INFO 67291 — [           main] o.h.e.t.j.p.i.JtaPlatformInitiator       : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
2020-02-14 11:08:20.636  INFO 67291 — [           main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
Payment onlyPaymentDO{paymentId=1945, paymentBatchJob=null, amountTotal=12.00}
PaymentPaymentDO{paymentId=1945, paymentBatchJob=null, amountTotal=12.00}
2020-02-14 11:08:21.108 ERROR 67291 — [           main] org.hibernate.AssertionFailure           : HHH000099: an assertion failure occurred (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session): org.hibernate.AssertionFailure: null identifier

org.hibernate.AssertionFailure: null identifier
at org.hibernate.engine.spi.EntityKey.<init>(EntityKey.java:51) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.internal.AbstractSharedSessionContract.generateEntityKey(AbstractSharedSessionContract.java:523) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.type.OneToOneType.isNull(OneToOneType.java:105) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.type.EntityType.resolve(EntityType.java:462) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.type.EntityType.resolve(EntityType.java:457) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.type.EntityType.replace(EntityType.java:358) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.type.AbstractType.replace(AbstractType.java:164) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.type.TypeHelper.replace(TypeHelper.java:204) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.event.internal.DefaultMergeEventListener.copyValues(DefaultMergeEventListener.java:488) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.event.internal.DefaultMergeEventListener.entityIsTransient(DefaultMergeEventListener.java:241) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.event.internal.DefaultMergeEventListener.entityIsDetached(DefaultMergeEventListener.java:318) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:172) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:70) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:108) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.internal.SessionImpl.fireMerge(SessionImpl.java:776) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.internal.SessionImpl.merge(SessionImpl.java:763) ~[hibernate-core-5.4.6.Final.jar:5.4.6.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:566) ~[na:na]
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:314) ~[spring-orm-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at com.sun.proxy.$Proxy73.merge(Unknown Source) ~[na:na]
at org.springframework.data.jpa.repository.support.SimpleJpaRepository.save(SimpleJpaRepository.java:557) ~[spring-data-jpa-2.2.0.RELEASE.jar:2.2.0.RELEASE]
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:566) ~[na:na]
at org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:371) ~[spring-data-commons-2.2.0.RELEASE.jar:2.2.0.RELEASE]
at org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:204) ~[spring-data-commons-2.2.0.RELEASE.jar:2.2.0.RELEASE]
at org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:657) ~[spring-data-commons-2.2.0.RELEASE.jar:2.2.0.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:621) ~[spring-data-commons-2.2.0.RELEASE.jar:2.2.0.RELEASE]
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:605) ~[spring-data-commons-2.2.0.RELEASE.jar:2.2.0.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:80) ~[spring-data-commons-2.2.0.RELEASE.jar:2.2.0.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:353) ~[spring-tx-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:99) ~[spring-tx-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139) ~[spring-tx-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:178) ~[spring-data-jpa-2.2.0.RELEASE.jar:2.2.0.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:93) ~[spring-aop-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) ~[spring-aop-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at com.sun.proxy.$Proxy86.save(Unknown Source) ~[na:na]
at com.swisscom.billing.testhibernate.PaymentsTxService.addPaymentBatchJob(PaymentsTxService.java:53) ~[main/:na]
at com.swisscom.billing.testhibernate.PaymentsTxService$$FastClassBySpringCGLIB$$4919717e.invoke(<generated>) ~[main/:na]
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:769) ~[spring-aop-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:747) ~[spring-aop-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:353) ~[spring-tx-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:99) ~[spring-tx-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:747) ~[spring-aop-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:689) ~[spring-aop-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at com.swisscom.billing.testhibernate.PaymentsTxService$$EnhancerBySpringCGLIB$$604ba717.addPaymentBatchJob(<generated>) ~[main/:na]
at com.swisscom.billing.testhibernate.StartupBean.onApplicationEvent(StartupBean.java:35) ~[main/:na]
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:566) ~[na:na]

如果我使用 H2 数据库,则不会发生错误。

配置:

spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQL95Dialect

有多种方法可以实现 OneToOne 关系。如果我改为(可能更典型): 所属类别:

@MapsId
private PaymentDO payment; 

我收到以下错误:

2020-02-14 11:25:41.048 ERROR 74847 — [           main] o.h.engine.jdbc.spi.SqlExceptionHelper   : ERROR: column paymentbat0_.payment_payment_id does not exist
Position: 8
2020-02-14 11:25:41.054  INFO 74847 — [           main] o.h.e.internal.DefaultLoadEventListener  : HHH000327: Error performing load command : org.hibernate.exception.SQLGrammarException: could not extract ResultSet

org.hibernate.exception.SQLGrammarException: could not extract ResultSet
at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:103) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:113) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:99) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:67) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.loader.Loader.getResultSet(Loader.java:2287) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:2045) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:2007) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.loader.Loader.doQuery(Loader.java:953) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:354) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:324) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.loader.Loader.loadEntity(Loader.java:2401) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:64) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.loader.entity.EntityLoader.loadByUniqueKey(EntityLoader.java:144) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.persister.entity.AbstractEntityPersister.loadByUniqueKey(AbstractEntityPersister.java:2384) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.type.EntityType.loadByUniqueKey(EntityType.java:745) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.type.EntityType.resolve(EntityType.java:467) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.engine.internal.TwoPhaseLoad.doInitializeEntity(TwoPhaseLoad.java:226) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.engine.internal.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:160) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.performTwoPhaseLoad(AbstractRowReader.java:255) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.finishUp(AbstractRowReader.java:215) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.loader.plan.exec.process.internal.ResultSetProcessorImpl.extractResults(ResultSetProcessorImpl.java:141) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:105) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.loader.entity.plan.AbstractLoadPlanBasedEntityLoader.load(AbstractLoadPlanBasedEntityLoader.java:197) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:4350) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.event.internal.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:570) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:538) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:208) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:333) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.event.internal.DefaultLoadEventListener.doOnLoad(DefaultLoadEventListener.java:108) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:74) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:118) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.internal.SessionImpl.fireLoadNoChecks(SessionImpl.java:1182) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1171) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.internal.SessionImpl.access$2000(SessionImpl.java:198) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.internal.SessionImpl$IdentifierLoadAccessImpl.doLoad(SessionImpl.java:2809) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.internal.SessionImpl$IdentifierLoadAccessImpl.lambda$load$1(SessionImpl.java:2790) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.internal.SessionImpl$IdentifierLoadAccessImpl.perform(SessionImpl.java:2746) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.internal.SessionImpl$IdentifierLoadAccessImpl.load(SessionImpl.java:2790) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.internal.SessionImpl.find(SessionImpl.java:3340) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
at org.hibernate.internal.SessionImpl.find(SessionImpl.java:3312) ~[hibernate-core-5.4.6.Final.jar:5.4.6.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:566) ~[na:na]
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:314) ~[spring-orm-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at com.sun.proxy.$Proxy74.find(Unknown Source) ~[na:na]
at org.springframework.data.jpa.repository.support.SimpleJpaRepository.findById(SimpleJpaRepository.java:281) ~[spring-data-jpa-2.2.0.RELEASE.jar:2.2.0.RELEASE]
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:566) ~[na:na]
at org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:371) ~[spring-data-commons-2.2.0.RELEASE.jar:2.2.0.RELEASE]
at org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:204) ~[spring-data-commons-2.2.0.RELEASE.jar:2.2.0.RELEASE]
at org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:657) ~[spring-data-commons-2.2.0.RELEASE.jar:2.2.0.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:621) ~[spring-data-commons-2.2.0.RELEASE.jar:2.2.0.RELEASE]
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:605) ~[spring-data-commons-2.2.0.RELEASE.jar:2.2.0.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:80) ~[spring-data-commons-2.2.0.RELEASE.jar:2.2.0.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:353) ~[spring-tx-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:99) ~[spring-tx-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139) ~[spring-tx-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:178) ~[spring-data-jpa-2.2.0.RELEASE.jar:2.2.0.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:93) ~[spring-aop-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) ~[spring-aop-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at com.sun.proxy.$Proxy83.findById(Unknown Source) ~[na:na]
at com.swisscom.billing.testhibernate.StartupBean.onApplicationEvent(StartupBean.java:28) ~[main/:na]
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:566) ~[na:na]

--> paymentbat0_. payment_ payment_id不存在!

如果我设置hibernate.id.disable_delayed_identity_inserts=true错误不会以任何方式改变。

我也尝试在版本 5.4.0.CR1 和 2 中使用 hibernate-core,但同样出现错误。此外,我注意到当我更新到 hibernate-core 5.4.0 时,我得到了较新版本的 hibernate-commons-annotations、javaassist 和 org.jboss:jandex。如果我这些回到用于 hibernate-core 5.3.* 的状态,错误仍然是相同的。因此,该错误肯定源自 hibernate-core 5.4.* 版本。

由于它是一个 Spring 应用程序,我使用 SimpleJpaRepository 的 save() 方法。正如我现在所看到的,尽管要保存的对象是新的,但该方法调用 EntityManager.merge() (请注意:不是 persist())。当在版本 5.3.* 上使用 hibernate-core 时,这可以正确保存对象。 调用 EntityManager.merge() 的事实是,ID 字段已填写。这是用于一对一关系的“共享主键”的结果。

我的问题是:使用 EntityManager.merge 的规则是否改变了?旧代码工作只是运气好还是 EntityManager.merge 工作应该足够宽松以检查对象是否尚未保存并正确保留? (在 Hibernate 的 Session.merge-Javadoc 中,我读到:“如果给定的实例未保存,则保存副本并将其作为新的持久实例返回。”)

作为解决方法,我调用 EntityManager.persist() 而不是 SimpleJpaRepository 的 save() ,这有帮助。然而,混合使用这两种 API 是不好的做法。


我有一个类似的问题,并且我已经设法解决了它。 尝试这个:

@OneToOne(cascade = CascadeType.MERGE)
@PrimaryKeyJoinColumn(name = "PAYMENT_ID", referencedColumnName = "PAYMENT_ID")
private PaymentDO payment;

据我所知,只要坚持下去PaymentBatchJob,Hibernate 采用不同的代码路径和底层merge()正在拨打电话而不是persist(),正如您在问题中所述。一项修复可能是添加CascadeType.MERGE.

请记住,此修复确实会影响底层Payment可以更新。

另一种可能的修复方法是使用Spring Data 持久化接口 https://docs.spring.io/spring-data/data-commons/docs/current/api/index.html?org/springframework/data/domain/Persistable.html,这使您可以控制确定对象是否是新对象,从而使存储库保存方法采用正确的路径(合并或保留)。

Sources:

  • https://doctorjw.wordpress.com/2020/09/23/spring-boot-2-2-x-and-onetoone-null-identifier/ https://doctorjw.wordpress.com/2020/09/23/spring-boot-2-2-x-and-onetoone-null-identifier/
  • https://github.com/spring-projects/spring-boot/issues/20181 https://github.com/spring-projects/spring-boot/issues/20181
  • https://hibernate.atlassian.net/browse/HHH-13413?attachmentOrder=asc https://hibernate.atlassian.net/browse/HHH-13413?attachmentOrder=asc
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 PostgreSQL 时,一对一关联在 5.4.0+ 上产生错误 的相关文章

随机推荐