【问题标题】:ManyToOne not mapped with the parent IDManyToOne 未映射到父 ID
【发布时间】:2017-12-15 16:46:48
【问题描述】:

我正在尝试在我的 Spring Boot 应用程序中实现测试,但我遇到了 ManyToOne/OneToMany 链接的问题。

似乎没有创建来自子对象的链接,而我使用 CascadeType = ALL。

我尝试在 BusinesDomain.addSubdomain 中创建它,添加“subDomain.domain(this);”但这会导致循环。

我发现了其他具有相同错误的主题,但似乎没有一个主题涵盖了我的问题。

您能帮我找出问题所在吗?

非常感谢!

这是我的实体

import lombok.AccessLevel;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.NonNull;
import lombok.Setter;
import lombok.experimental.Accessors;

@Accessors(fluent = true)
@Data
@Entity
@NoArgsConstructor
public class BusinessDomain {
    @Setter(AccessLevel.NONE)
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private long id;

    @NonNull
    @Column(unique=true)
    private String name;

    @OneToMany(mappedBy = "domain", cascade = CascadeType.ALL, orphanRemoval = true)
    private Set<BusinessSubDomain> subDomains = new LinkedHashSet<>();

    public void addSubDomain(BusinessSubDomain subDomain) {
        subDomains.add(subDomain);
    }
}

@Accessors(fluent = true)
@Data
@Entity
@NoArgsConstructor
public class BusinessSubDomain {
    @Setter(AccessLevel.NONE)
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private long id;

    @ManyToOne(optional = false)
    @JoinColumn(name = "business_domain_id", referencedColumnName="id")
    private BusinessDomain domain;
}

我的服务等级:

@Override
public BusinessDomain saveOrUpdate(BusinessDomain businessDomain) throws OrcaException {
    try {
        BusinessDomain domain = businessDomainRepository.findByName(businessDomain.name());
        if(null == domain) {
        // Repository class not overriden (extends CrudRepository<BusinessDomain, Long>)
            return businessDomainRepository.save(businessDomain);
        } else {
            domain.description(businessDomain.description());
            domain.subDomains(businessDomain.subDomains());
            return businessDomainRepository.save(domain);
        }
    } catch (Exception e) {
        throw new OrcaException(e);
    }
}

还有我的测试:

@RunWith(SpringRunner.class)
@SpringBootTest
public class BusinessDomainTest {
    @Test
    @Transactional
    public void createBusinessDomainWithSubDomain() throws OrcaException {
        BusinessDomain passengerBusinessDomain = new BusinessDomain().name(DOMAIN_NAME).description(DOMAIN_DESCRIPTION);
        BusinessSubDomain distributionBusinessSubDomain = new BusinessSubDomain().name(SUBDOMAIN_NAME)
                .description(SUBDOMAIN_DESCRIPTION);
        passengerBusinessDomain.addSubDomain(distributionBusinessSubDomain);
        businessDomainService.saveOrUpdate(passengerBusinessDomain);
        BusinessDomain domain = businessDomainService.findByName(DOMAIN_NAME);
    }
}

这样我收到错误消息:

[主要] 信息 com.myproject.project.test.model.soadatamodel.business.domaining.BusinessDomainTest - 在 24.161 秒内启动 BusinessDomainTest(JVM 运行 26.159) [main] INFO org.springframework.test.context.transaction.TransactionContext - 开始测试上下文的事务 (1) [DefaultTestContext@76480730 testClass = BusinessDomainTest, testInstance = com.myproject.project.test.model.soadatamodel.business.domaining.BusinessDomainTest@405a296e, testMethod = createBusinessDomainWithArea@BusinessDomainTest, testException = [null],mergedContextConfiguration = [WebMergedContextConfiguration@5f5c2451 testClass = BusinessDomainTest,位置 = '{}',类 = '{class com.myproject.project.TestApplication}',contextInitializerClasses = '[]',activeProfiles = '{}',propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = 设置[org.springframework.boot.test.context.SpringBootTestContextCustomizer@6eceb130, org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@47db50c5, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@68ceda24], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', 父 = [null]]];事务管理器 [org.springframework.orm.jpa.JpaTransactionManager@28d97205];回滚 [真] [主要] 信息 org.hibernate.hql.internal.QueryTranslatorFactoryInitiator - HHH000397:使用 ASTQueryTranslatorFactory 休眠:选择 businessdo0_.id 作为 id1_1_,businessdo0_.description 作为 descript2_1_, businessdo0_.name as name3_1_ from BusinessDomain businessdo0_ where businessdo0_.name=? Hibernate:调用 hibernate_sequence 的下一个值 Hibernate:调用 hibernate_sequence [main] WARN 的下一个值 org.hibernate.engine.jdbc.spi.SqlExceptionHelper - SQL 错误:23502, SQLState: 23502 [主] 错误 org.hibernate.engine.jdbc.spi.SqlExceptionHelper - NULL 不允许 对于“BUSINESS_DOMAIN_ID”列; SQL 语句:插入 BusinessSubDomain(描述、business_domain_id、name、id)值 (?, ?, ?, ?) [23502-168] [主要] 信息 org.hibernate.engine.jdbc.batch.internal.AbstractBatchImpl - HHH000010:在批处理发布时,它仍然包含 JDBC 语句 org.springframework.dao.DataIntegrityViolationException:不能 执行语句; SQL [不适用];约束[空];嵌套异常是 org.hibernate.exception.ConstraintViolationException:不能 执行语句 org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:278) 在 org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:244) 在 org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:488) 在 org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:59) 在 org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213) 在 org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:147) 在 org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 在 org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:133) 在 org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 在 org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) 在 org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 在 org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:57) 在 org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 在 org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213) 在 com.sun.proxy.$Proxy134.findByName(未知来源) com.myproject.project.service.soadatamodel.business.domaining.impl.BusinessDomainServiceImpl.findByName(BusinessDomainServiceImpl.java:40) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 在 java.lang.reflect.Method.invoke(Method.java:483) 在 org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:333) 在 org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190) 在 org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) 在 org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99) 在 org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:282) 在 org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) 在 org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 在 org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213) 在 com.sun.proxy.$Proxy137.findByName(未知来源) com.myproject.project.test.model.soadatamodel.business.domaining.BusinessDomainTest.createBusinessDomainWithArea(BusinessDomainTest.java:82) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)休眠: 调用 hibernate_sequence Hibernate 的下一个值:插入 BusinessDomain (description, name, id) 值 (?, ?, ?) Hibernate: 插入 BusinessSubDomain(描述、business_domain_id、名称、 id) 值 (?, ?, ?, ?) 无法执行语句; SQL [不适用]; 约束[空];嵌套异常是 org.hibernate.exception.ConstraintViolationException:不能 执行语句 org.springframework.dao.DataIntegrityViolationException:不能 执行语句; SQL [不适用];约束[空];嵌套异常是 org.hibernate.exception.ConstraintViolationException:不能 执行语句

在 java.lang.reflect.Method.invoke(Method.java:483) 在 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.invokeExplosively(FrameworkMethod.java:47) 在 org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) 在 org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75) 在 org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86) 在 org.junit.rules.ExpectedException$ExpectedExceptionStatement.evaluate(ExpectedException.java:239) 在 org.junit.rules.RunRules.evaluate(RunRules.java:20) 在 org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84) 在 org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) 在 org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252) 在 org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) 在 org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) 在 org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) 在 org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) 在 org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) 在 org.junit.runners.ParentRunner$2.evaluate(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.java:363) 在 org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) 在 org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283) 在 org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173) 在 org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) 在 org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128) 在 org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203) 在 org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155) 在 org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) 引起:org.hibernate.exception.ConstraintViolationException:可以 不执行语句 org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:112) 在 org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42) 在 org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:109) 在 org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:95) 在 org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:207) 在 org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:45) 在 org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2949) 在 org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3449) 在 org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:89) 在 org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:582) 在 org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:456) 在 org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:337) 在 org.hibernate.event.internal.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:50) 在 org.hibernate.internal.SessionImpl.autoFlushIfRequired(SessionImpl.java:1251) 在 org.hibernate.internal.SessionImpl.list(SessionImpl.java:1319) 在 org.hibernate.internal.QueryImpl.list(QueryImpl.java:87) 在 org.hibernate.jpa.internal.QueryImpl.list(QueryImpl.java:606) 在 org.hibernate.jpa.internal.QueryImpl.getSingleResult(QueryImpl.java:529) 在 org.hibernate.jpa.criteria.compile.CriteriaQueryTypeQueryAdapter.getSingleResult(CriteriaQueryTypeQueryAdapter.java:54) 在 org.springframework.data.jpa.repository.query.JpaQueryExecution$SingleEntityExecution.doExecute(JpaQueryExecution.java:206) 在 org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:85) 在 org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:116) 在 org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:106) 在 org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:483) 在 org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:461) 在 org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 在 org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:61) 在 org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 在 org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99) 在 org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:282) 在 org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) 在 org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 在 org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136) ... 56 更多原因:org.h2.jdbc.JdbcSQLException: NULL not allowed 对于“BUSINESS_DOMAIN_ID”列; SQL 语句:插入 BusinessSubDomain(描述、business_domain_id、name、id)值 (?, ?, ?, ?) [23502-168] 在 org.h2.message.DbException.getJdbcSQLException(DbException.java:329) 在 org.h2.message.DbException.get(DbException.java:169) 在 org.h2.message.DbException.get(DbException.java:146) 在 org.h2.table.Column.validateConvertUpdateSequence(Column.java:293) 在 org.h2.table.Table.validateConvertUpdateSequence(Table.java:689) 在 org.h2.command.dml.Insert.insertRows(Insert.java:120) 在 org.h2.command.dml.Insert.update(Insert.java:84) 在 org.h2.command.CommandContainer.update(CommandContainer.java:75) 在 org.h2.command.Command.executeUpdate(Command.java:230) 在 org.h2.jdbc.JdbcPreparedStatement.executeUpdateInternal(JdbcPreparedStatement.java:156) 在 org.h2.jdbc.JdbcPreparedStatement.executeUpdate(JdbcPreparedStatement.java:142) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 在 java.lang.reflect.Method.invoke(Method.java:483) 在 org.apache.tomcat.jdbc.pool.StatementFacade$StatementProxy.invoke(StatementFacade.java:114) 在 com.sun.proxy.$Proxy130.executeUpdate(Unknown Source) 在 org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:204) ... 84 更多 [主要] 信息 org.springframework.test.context.transaction.TransactionContext - 为测试上下文回滚事务 [DefaultTestContext@76480730 testClass = BusinessDomainTest, testInstance = com.myproject.project.test.model.soadatamodel.business.domaining.BusinessDomainTest@405a296e, testMethod = createBusinessDomainWithArea@BusinessDomainTest, testException = [错误代码:UNKNWN001] 未知错误 [异常 :org.springframework.dao.DataIntegrityViolationException:不能 执行语句; SQL [不适用];约束[空];嵌套异常是 org.hibernate.exception.ConstraintViolationException:不能 执行语句],mergedContextConfiguration = [WebMergedContextConfiguration@5f5c2451 testClass = BusinessDomainTest,位置 = '{}',类 = '{class com.myproject.project.TestApplication}',contextInitializerClasses = '[]',activeProfiles = '{}',propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = 设置[org.springframework.boot.test.context.SpringBootTestContextCustomizer@6eceb130, org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@47db50c5, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@68ceda24], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', 父 = [null]]]。 [主要] 信息 org.springframework.test.context.transaction.TransactionContext - 开始测试上下文的事务 (1) [DefaultTestContext@76480730 testClass = BusinessDomainTest, testInstance = com.myproject.project.test.model.soadatamodel.business.domaining.BusinessDomainTest@685e8e17, testMethod = createSimpleBusinessDomain@BusinessDomainTest, testException = [null],mergedContextConfiguration = [WebMergedContextConfiguration@5f5c2451 testClass = BusinessDomainTest,位置 = '{}',类 = '{class com.myproject.project.TestApplication}',contextInitializerClasses = '[]',activeProfiles = '{}',propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = 设置[org.springframework.boot.test.context.SpringBootTestContextCustomizer@6eceb130, org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@47db50c5, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@68ceda24], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', 父 = [null]]];事务管理器 [org.springframework.orm.jpa.JpaTransactionManager@28d97205];回滚 [真]

【问题讨论】:

  • 要在子域上设置“域”吗?也就是设置关系的双方
  • 您好,欢迎来到 Stack Overflow,请花点时间通过 welcome tour 了解您在此处的方式(并获得您的第一个徽章),阅读如何创建 Minimal, Complete, and Verifiable example并检查How to Ask Good Questions,这样您就可以增加获得反馈和有用答案的机会......请不要添加太多内容,因为没有多少用户可能会提供帮助
  • 你好,我试图在子域上设置域,但我得到了一个无限循环(参见我的第一篇文章):(

标签: spring hibernate jpa spring-boot


【解决方案1】:

我终于明白了。

首先,实体加法器必须是

public void addSubDomain(BusinessSubDomain subDomain) {
    subDomains.add(subDomain);
    subDomain.domain(this);
}

但这会导致无限循环并无限调用哈希方法。

我在我的实体中使用@Getter 和@Setter 而不是@Data 解决了这个问题(由lombok 引起)。

谢谢

【讨论】:

    猜你喜欢
    • 2012-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-02
    • 2013-02-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-24
    相关资源
    最近更新 更多