升级后,@MapsId在保存现有实体时抛出错误,但在其他方面工作正常



我正在将Spring Boot 1.5.21项目(Java 8u221)升级到Spring Boot 2.1.9(Java 11.0.2-open).在这两种情况下,我们都使用带有Spring启动程序和依赖解析程序的gradle构建,因此底层Spring、JPA和Hibernate库的版本都是Spring管理的。

该项目有一个可选的一对一映射,其中子实体从父实体生成的ID中获取其ID。在Spring Boot 1版本的项目中,关系配置如下:

@Entity
@Table(name = "PARENT_OBJECT", schema = "MYSCHEMA")
public class ParentObject implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "PARENT_OBJECT_ID_SEQ")
@SequenceGenerator(name = "PARENT_OBJECT_ID_SEQ", sequenceName = "MYSCHEMA.PARENT_OBJECT_ID_SEQ")
protected Long id;
@OneToOne(optional = true, mappedBy = "parentObject", cascade = CascadeType.ALL, orphanRemoval = true)
@Valid
protected ChildObject childObject;
// Other fields and methods
}
@Entity
@Table(name = "CHILD_OBJECT", schema = "MYSCHEMA")
public class ChildObject implements Serializable {
@Id
@Column(name = "parent_object_id", unique = true, nullable = false, insertable = true, updatable = false)
private Long parentObjectId;
@OneToOne
@MapsId
@PrimaryKeyJoinColumn
@JsonIgnore
private ParentObject parentObject;
// Other fields and methods
}

当我更新到Spring Boot 2时,我不得不更新很多JPA设置,有一件事特别被抱怨,那就是生成的查询查找的是'PARENTOBJECT_ID'而不是'PARENT_OBJECT_ID',所以我对此进行了一点研究,发现了一篇文章解释了如何使用@JoinColumn修复一对一映射的列名,并将parentObject字段的子对象注释更新为以下内容:

@OneToOne
@MapsId
@JoinColumn(name = "parent_object_id")
@JsonIgnore
private ParentObject parentObject;

我完全删除了@PrimaryKeyJoinColumn,因为文档似乎建议,如果你想让Hibernate处理ID的分配,你应该使用@MapsId,如果你要自己管理它们,那就是你使用@PrimaryKeyJoinColumn的时候。

这个配置适用于我的所有测试,除了2:控制器的UPDATE集成测试(POST测试运行得很好,当ParentObject第一次与其关联的ChildObject一起创建时)仅这两个测试我得到的错误是

org.springframework.org.jpa.JpaSystemException:试图从null一对一属性[org.mycompany.myproject.mymodule.mysubmodule.ChildObject.pparentObject]分配id;嵌套异常为org.hibernate.id.IdentifierGenerationException:试图从空的一对一属性[org.mycompany.myproject.mymodule.mysubmodule.ChildObject.pparentObject]分配id

奇怪的是,这些实体及其关联的所有存储库集成测试以及所有其他控制器集成测试都通过了,包括新ParentObject与其新ChildObject一起发布的测试。我到处寻找可能的解决方案,但我读到的每一篇文章似乎都表明我使用的配置应该有效。我还尝试了一些替代配置,比如使用@PrimaryKeyJoinColumn和自己设置ID字段,在ChildObject的ID上使用ID生成器(尽管@MapsId的目的是告诉系统使用ParentObject的ID),通常我最终会遇到更多失败的测试,并出现以下错误:

org.springframework.org.jpa.JpaSystemException:在调用save()之前,必须手动分配此类的id:org.mycompany.myproject.mymodule.mysubmodule.ChildObject;嵌套异常为org.hibernate.id.IdentifierGenerationException:在调用save()之前,必须手动分配此类的id:org.mycompany.myproject.mymodule.mysubmodule.ChildObject

尽管有时我会收到无法"从null分配id"的原始错误。在这一点上,我不知道这是如何错误配置的,或者是什么其他因素在影响事情。在这一点上,我愿意尝试所有的建议。

为了完整起见,以下是应用程序中的一堆代码片段堆栈跟踪中的相关行号用注释表示我省略了控制器代码,因为它没有什么特别之处;POST和PUT方法都调用相同的服务方法;它们只是在不同的端点,PUT在调用服务保存方法之前首先检查对象是否存在于DB中。以下是为ParentObject:调用JPA repo的服务方法

@Service
@Transactional(readOnly = true)
public class ParentObjectServiceImpl implements ParentObjectService {
// other fields and other methods
@Autowired
private ParentObjectRepository parentObjectRepository;
@Transactional(readOnly = false)
@Override
public ParentObject saveParentObject(final ParentObject parentObject) {
parentObject.prepForPersistence();
return parentObjectRepository.save(parentObject); //Line 93
}
}

这是我的JPA存储库:

public interface ParentObjectRepository extends CrudRepository<ParentObject, Long> {
// custom methods, no override for save though
}

这里是ParentObjectprepForPersistence()方法:

public void prepForPersistence() {
if(childObject != null) {
childObject.setParentObject(this);
// In some iterations of the code in trying to solve this, I also had the following line
//childObject.setParentObjectId(this.id);
}
}

以下是两个测试(一个通过,一个失败):

@RunWith(SpringRunner.class)
@SpringBootTest(classes = MyApplication.class)
@WebAppConfiguration
// This profile disabled csrf for testing, and sets some env variables
@ActiveProfiles("integration-test")
@Transactional
public class ParentObjectControllerTest {
@Autowired
private WebApplicationContext context;
private MockMvc mockMvc;
@Before
public void setUp() throws Exception {
mockMvc = MockMvcBuilders.webAppContextSetup(context)
.apply(springSecurity())
.build();
} 
// This test PASSES
@Test
@WithMockUser(roles = {"MY_APP_ADMIN"}, username = TEST_USER)
@Sql(scripts = "/db-scripts/bootstrap.sql")
public void testPostParentObjectWithChildObject() {
final ChildObject childObject = new ChildObject();
// set some properties on childObject that don't relate to ParentObject
final ParentObject parentObject = new ParentObject();
// set some properties on parentObject that don't relate to ChildObject
parentObject.setChildObject(childObject);
final ParentObject result = given().mockMvc(mockMvc).contentType(ContentType.JSON)
.and().body(item).log().all()
.when().post("/parent-objects")
.then().log().all().statusCode(201).contentType(ContentType.JSON)
.and().body(matchesJsonSchemaInClasspath("json-schemas/parent-object.json"))
.and().body("username", equalTo(TEST_USER))
.extract().as(ParentObject.class);
assertThat(result.getId(), is(notNullValue()));
assertThat(result.getChildObject().getParentObjectId(), is(result.getId()));
}
// This test FAILS with the 'attempted to assign id from null one-to-one property' error
@Test
@WithMockUser(roles = {"MY_APP_ADMIN"}, username = TEST_USER)
// Inserts a ParentObject record with ID -1
@Sql(scripts = "/db-scripts/bootstrap.sql")
public void testPutParentObjectWithChildObject() {
final ChildObject childObject = new ChildObject();
// set some properties on childObject that don't relate to ParentObject
final Long EXISTING_ID = -1L;
final ParentObject parentObject = new ParentObject();
parentObject.setId(EXISTING_ID);
parentObject.setChildObject(childObject);
final ParentObject result = given().mockMvc(mockMvc).contentType(ContentType.JSON)
.and().body(item).log().all()
.when().put("/parent-objects/{parentObjectId}", parentObject.getId()) //line 260
.then().log().all().statusCode(200)
.extract().as(ParentObject.class);
assertThat(result.getId(), is(EXISTING_ID));
assertThat(result.getChildObject().getParentObjectId(), is(EXISTING_ID));
}

这是完整的堆栈跟踪:

由于以下错误,HTTPStatus=INTERNAL_SERVER_ERROR响应:org.springframework.orgm.jpa.JpaSystemException:试图从null一对一属性[org.mycompany.myproject.mymodule.mysubmodule.ChildObject.pparentObject]分配id;嵌套异常为org.hubinate.id.IdentifierGenerationException:试图从null一对一属性[org.mycompany.myproject.mymodule.mysubmodule.ChildObject.pparentObject]分配id网址:org.springframework.orm.jpa.vender.Hibernate JpaDialect.covertHibernate AccessException(Hibernate jpa Dialect.java:352)网址:org.springframework.om.jpa.vendor。Hibernate JpaDialection.translateExceptionIfPossible(Hibernate jpa Dialection.java:254)网址:org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:528)网址:org.springframework.dao.support.ChainedSistenceExceptionTranslator.translateExceptionIfPossible(ChainedSistenceexceptionTranslator.java:61)网址:org.springframework.dao.support.DataAccessUtils.translateIfNenecessary(DataAccessUtils.java:242)位于org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.ioke(PersistenceExceptionTranslationInterceptor.java:153)网址:org.springframework.aop.framework.ReflectiveMethodInvocation.prough(ReflectiveMethodInvocation.java:186)位于org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.ioke(CrudMethodMetadataPostProcessor.java:144)网址:org.springframework.aop.framework.ReflectiveMethodInvocation.prough(ReflectiveMethodInvocation.java:186)网址:org.springframework.data.jpa.restore.support.CrudMethodMetadataPostProcessor$ExposeRepositoryInvocationInterceptor.ioke(CrudMethodMetadataPostProcessor.java:364)网址:org.springframework.aop.framework.ReflectiveMethodInvocation.prough(ReflectiveMethodInvocation.java:186)位于org.springframework.aop.intercept.ExposeInvocationInterceptor.ioke(ExposeInvocation interceptor.java:93)网址:org.springframework.aop.framework.ReflectiveMethodInvocation.prough(ReflectiveMethodInvocation.java:186)位于org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.ioke(SurroundingTradeDetectorMethodinterceptor.java:61)网址:org.springframework.aop.framework.ReflectiveMethodInvocation.prough(ReflectiveMethodInvocation.java:186)网址:org.springframework.aop.framework.JdkDynamicAopProxy.invoke网址:com.sun.proxy.$Proxy249.save(未知来源)网址:org.mycompany.myproject.mymodule.ParentObjectServiceImpl.saveParentObject(ParentObjectServiceImpl.java:93)网址:org.mycompany.myproject.mymodule.ParentObjectServiceImpl$$FastClassBySpringCGLIB$$86531367.invoke()位于org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)网址:org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAoProxy.java:750)网址:org.springframework.aop.framework.ReflectiveMethodInvocation.prough(ReflectiveMethodInvocation.java:163)位于org.springframework.transaction.intercept.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:295)位于org.springframework.transaction.interceptor.TransactionInterceptor.ininvoke(TransactionInterceptor.java:98)网址:org.springframework.aop.framework.ReflectiveMethodInvocation.prough(ReflectiveMethodInvocation.java:186)网址:org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.cintercept(CglibAoProxy.java:689)位于org.mycompany.myproject.mymodule.ParentObjectServiceImpl$$EnhancerBySpringCGLIB$$d3a0c3ee.saveChecklistItem()网址:org.mycompany.myproject.mymodule.ParentObjectController.putParentObject(ParentObjectControlr.java:78)位于java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)位于java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)位于java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)位于java.base/java.lang.reflect.Method.ioke(Method.java:566)位于org.springframework.web.method.support.IInvocableHandlerMethod.doInvoke(InvocableHandler method.java:190)位于org.springframework.web.method.support.InvocaleHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)位于org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105)位于org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:893)网址:org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandledAdapter.java:798)网址:org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethod Adapter.java:87)位于org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)位于org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)网址:org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)网址:org.springframework.web.servlet.FrameworkServlet.doPut(FrameworkServlet.java:920)位于javax.servlet.httpHttpServlet.service(HttpServlet.java:668)网址:org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)位于org.springframework.test.web.servlet.TestDispatcherServlet.service(TestDispatcherServlet.java:72)位于javax.servlet.httpHttpServlet.service(HttpServlet.java:750)网址:org.springframework.mok.web.MockFilterChain$ServletFilterProxy.doFilter(MockFilterChain.java:167)网址:org.springframework.mok.web.MockFilterChain.doFilter(MockFilterChain.java:134)网址:org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:320)网址:org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)网址:org.springframework.security.web.access.eccept.FilterSecurityInterceptor.ioke(FilterSecurityIntercepter.java:127)网址:org.springframework.security.web.access.eccept.FilterSecurityInterceptor.doFilter(FilterSecurityIntercepter.java:91)网址:org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)网址:org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:119)网址:org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)网址:org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137)网址:org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)网址:org.springframework.security.web.authentication.AnnonymousAuthenticationFilter.doFilter(匿名身份验证过滤器.java:111)网址:org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)网址:org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAware RequestFilter.java:170)网址:org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)网址:org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)网址:org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)网址:org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessor.java:200)网址:org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)网址:org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)网址:org.springframework.security.web.authentication.loogout.LogoutFilter.doFilter(LogoutFilter.java:116)网址:org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)网址:org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:97)网址:org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequest filter.java:119)网址:org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)网址:org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:74)网址:org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequest filter.java:119)网址:org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)位于org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)网址:org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)位于org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegration Filter.java:56)网址:org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequest filter.java:119)网址:org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)网址:org.springframework.security.web.FilterChainPoxy.doFilterInternal(FilterChainProxy.java:215)网址:org.springframework.security.web.FilterChainPoxy.doFilter(FilterChainProxy.java:178)网址:org.springframework.mok.web.MockFilterChain.doFilter(MockFilterChain.java:134)网址:org.springframework.test.web.servlet.MockMvc.execure(MockMvc.java:183)位于io.ressured.module.mockmvc.internal.MockMvcRequestSenderImpl.performRequest(MockMvcRequestSenderImpl.java:218)位于io.ressured.module.mockmvc.internal.MockMvcRequestSenderImpl.sendRequest(MockMvcRequestSenderImpl.java:447)位于io.ressured.module.mockmvc.internal.MockMvcRequestSenderImpl.put(MockMvcRequestSenderImpl.java:504)位于io.ressured.module.mockmvc.internal.MockMvcRequestSenderImpl.put(MockMvcRequestSenderImpl.java:100)网址:org.mycompany.myproject.mymodule.ParentObjectControllerTest.testPutParentObjectWithChildObject(ParentObjectController Test.java:260)位于java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)位于java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)位于java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)位于java.base/java.lang.reflect.Method.ioke(Method.java:566)网址:org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)网址:org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)位于org.junit.runners.model.FrameworkMethod.invokeExplorery(FrameworkMethod.java:47)位于org.junit.internal.runners.statements.InvokeMethod.eevaluate(InvokeMethod.java:17)位于org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:74)位于org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:84)网址:org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)位于org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)位于org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)网址:org.springframework.test.context.junit4.statements.SpringRepeat.eevaluate(SpringRepeat.java:84)网址:org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)位于org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)位于org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)网址:org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)网址:org.junit.runners.ParentRunner$1schedule(ParentRunner.java:71)网址:org.junit.runners.ParentRunner.runChildren(ParentRunnr.java:288)网址:org.junit.runners.ParentRunner.access$000(ParentRunner:58)网址:org.junit.runners.ParentRunner$2.eevaluate(ParentRunner.java:268)位于org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)位于org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)网址:org.junit.runners.ParentRunner.run(ParentRunner:363)位于org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)网址:org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.runTestClass(JUnitTestClassExecutor.java:110)网址:org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:58)网址:org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:38)网址:org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.productTestClass(AbstractJUnitTestClassProcessor.java:62)网址:org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.productTestClass(SuiteTestClassProcessor.java:51)位于java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)位于java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)位于java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)位于java.base/java.lang.reflect.Method.ioke(Method.java:566)网址:org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDisptch.java:36)网址:org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDisptch.java:24)位于org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)位于org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)网址:com.sun.proxy.$Proxy5.processTestClass(未知来源)网址:org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:118)位于java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)位于java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)位于java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)位于java.base/java.lang.reflect.Method.ioke(Method.java:566)网址:org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDisptch.java:36)网址:org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDisptch.java:24)位于org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:182)位于org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:164)位于org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:412)网址:org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)网址:org.gradle.internal.concurrent.ManagedExecutiorImpl$1.run(ManagedExecutiorimpl.java:48)位于java.base/java.util.concurrent.ThreadPoolExecutiator.runWorker(ThreadPoolExecutiator.java:1128)位于java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)位于org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)位于java.base/java.lang.Thread.run(线程.java:834)导致原因:org.hibernate.id.IdentifierGenerationException:试图从null一对一属性[org.mycompany.myproject.mymodule.mysubmodule.ChildObject.pparentObject]分配id网址:org.hibernate.id.ForeignGenerator.generate(ForeignGenerator.java:90)位于org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventLister.java:119)位于org.hibernate.event.internal.DefaultMergeEventListener.saveTransientEntity(DefaultMergeEventLister.java:287)位于org.hibernate.event.internal.DefaultMergeEventListener.entityIsTransient(DefaultMergeEventLister.java:259)位于org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventLister.java:191)位于org.hibernate.internal.SessionImpl.fireMerge(SessionImpl.java:927)位于org.hibernate.internal.SessionImpl.merge(SessionImpl.java:897)网址:org.hibernate.engine.spi.CastingActions$6.cacade(CascadingActions.java:261)网址:org.hibernate。engine.internal.Castcade.cascadeToOne(Cascade.java:490)网址:org.hibernate。engine.internal。Cascade.cascadeAssociation(Cascade.java:415)位于org.hibernate.engine.internal.Castcade.cascadeProperty(Cascade.java:216)网址:org.hibernate。engine.internal.Castcade.Cascade(Cascade.java:149)位于org.hibernate.event.internal.DefaultMergeEventListener.cascadeOnMerge(DefaultMergeEventLister.java:532)位于org.hibernate.event.internal.DefaultMergeEventListener.entityIsDetailed(DefaultMergeEventLister.java:361)位于org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventLister.java:188)位于org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventLister.java:72)位于org.hibernate.internal.SessionImpl.fireMerge(SessionImpl.java:905)位于org.hibernate.internal.SessionImpl.merge(SessionImpl.java:891)位于java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)位于java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)位于java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)位于java.base/java.lang.reflect.Method.ioke(Method.java:566)位于org.springframework.om.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreater.java:310)网址:com.sun.proxy.$Proxy214.merge(未知来源)网址:org.springframework.data.jpa.repository.support.SimpleJpaRepository.save(SimpleJpaRepository.java:538)位于java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)位于java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)位于java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)位于java.base/java.lang.reflect.Method.ioke(Method.java:566)位于org.springframework.data.restore.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:359)网址:org.springframework.data.repository.core.support.RepositoryComposition.ininvoke(RepositoryComposition.java:200)位于org.springframework.data.restore.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.ioke(RepositoryFactorySupport.java:644)网址:org.springframework.aop.framework.ReflectiveMethodInvocation.prough(ReflectiveMethodInvocation.java:186)位于org.springframework.data.restore.core.support.RepositoryFactorySupport$QueryExecutiorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:608)位于org.springframework.data.restore.core.support.RepositoryFactorySupport$QueryExecutiorMethodInterceptorLambda$invoke$3(RepositoryFactorySupport.java:595)位于org.springframework.data.restore.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.ioke(RepositoryFactorySupport.java:595)网址:org.springframework.aop.framework.ReflectiveMethodInvocation.prough(ReflectiveMethodInvocation.java:186)位于org.springframework.data.project.DefaultMethodInvokingMethodInterceptor.ioke(DefaultMethodInvokingMethodInterceptor.java:59)网址:org.springframework.aop.framework.ReflectiveMethodInvocation.prough(ReflectiveMethodInvocation.java:186)位于org.springframework.transaction.intercept.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:295)位于org.springframework.transaction.interceptor.TransactionInterceptor.ininvoke(TransactionInterceptor.java:98)网址:org.springframework.aop.framework.ReflectiveMethodInvocation.prough(ReflectiveMethodInvocation.java:186)位于org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.ioke(PersistenceExceptionTranslationInterceptor.java:139)…还有140个

提前感谢您的建议和帮助!

我认为这是一个错误,但如果有人有解决方法,我仍然对它们感兴趣。我最初在hibernate上发现了一个似乎与问题相匹配的bug,但它被注册为只影响5.2系列,并被标记为"已修复"。由于我们的项目使用的是5.3系列,我继续前进。不过,从春季开始挖掘提交的bug,一条面包屑线索让我发现了这个5.3系列的bug:https://hibernate.atlassian.net/browse/HHH-13413这与我最初发现的5.2系列错误有关,与5.3的总结相反,这似乎表明,自5.2系列以来,这一直是一个问题,不应该在5.3系列中起作用,因为5.3系列错误不仅被标记为5.2系列错误的重复,当我仔细观察5.2错误时,它表示它的修复版本直到5.4才出现:https://hibernate.atlassian.net/browse/HHH-12436

因此,我将尝试降级到上一个有效的5.2系列,并升级到5.4系列。。。我只是不确定这两者将如何与spring数据jpa的其余功能配合使用,这本身可能是一个大问题。

更新:除了因为我们使用的是java11而遇到问题之外(https://hibernate.atlassian.net/browse/HHH-12924->我不得不使用javassist:3.23.0-GA来获得hibernate内核:5.2.13.最终才能工作),降级成功地使一对一映射再次工作。所有其他测试也都通过了。然而,我还没有对这个解决方案进行广泛的测试,因为我更喜欢基于升级的解决方案。

更新2:能够升级到Spring Boot 2.2.0(它使用Hibernate 5.4,这是修复一对一映射的特殊错误的地方)!它需要对我的序列进行一些更改,但升级并不太痛苦;甚至不需要使用降级标志!如果碰巧您的映射问题没有得到解决,那么会有一个"使用5.2行为"标志,因为他们仍在解决各种映射场景的问题。有关这一点的更多详细信息,请参阅他们的5.4迁移说明:https://github.com/hibernate/hibernate-orm/blob/61cddad76d5bba951805fa7ed90cc149d404841c/migration-guide.adoc

相关内容

  • 没有找到相关文章

最新更新