这是我的观察对象:
步骤(4节课(
@Entity
@Table(name = "step")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@Data
public abstract class AbstractStep implements Serializable {
@EmbeddedId
private StepKey key;
@Column
private String htmlContent;
@Column
private Boolean passed;
}
@Builder
@Getter
@Setter
@EqualsAndHashCode
@Embeddable
public class StepKey implements Serializable {
@Column
private Integer numberStep;
@ManyToOne
private TestableEquipment equipment;
}
@Entity
@Table(name = "esthetic_step")
@Data
@EqualsAndHashCode(callSuper = false)
public class EstheticStep extends AbstractStep {
@Column
@Enumerated(EnumType.STRING)
private EstheticState selectedEstheticState;
}
@Entity
@Table(name = "functional_step")
@Data
@EqualsAndHashCode(callSuper = false)
public class FunctionalStep extends AbstractStep {
@Column
private String labelBreakdown;
}
设备:
@Entity
@Table(name = "testable_equipment")
@Getter
@Setter
@EqualsAndHashCode
public class TestableEquipment implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToMany(mappedBy = "key.equipment", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private List<AbstractStep> steps = new ArrayList<>();
}
实际上这些类中有更多的字段,但我简化了以使其更具可读性。
我的问题是我用 3 个步骤创建一个设备:
equipment = Equipment
.builder()
.id(1L)
.build();
List<AbstractStep> equipmentSteps = new ArrayList<>();
fs1 = new FunctionalStep();
fs1.setHtmlContent("htmlContent1");
fs1.setKey(new StepKey(1, equipment));
fs1.setLabelBreakdown("breakdown1");
fs1.setPassed(null);
fs2 = new FunctionalStep();
fs2.setHtmlContent("htmlContent2");
fs2.setKey(new StepKey(2, equipment));
fs2.setLabelBreakdown("breakdown2");
fs2.setPassed(null);
fs3 = new FunctionalStep();
fs3.setHtmlContent("htmlContent3");
fs3.setKey(new StepKey(3, equipment ));
fs3.setLabelBreakdown("breakdown3");
fs3.setPassed(null);
equipmentSteps.add(fs1);
equipmentSteps.add(fs2);
equipmentSteps.add(fs3);
equipment.setSteps(equipmentSteps);
equipmentRepository.saveAndFlush(equipment);
当我尝试调用: equipmentRepository.findOne(1L(;
休眠循环在同一选择中,并抛出 StackOverflowException。
我不明白,因为我做一个双向关联。
有人有想法吗?
编辑
方法findOne((在测试中调用
@Test(expected = ServiceEquipmentException.class)
public void beginTestTestWithEstheticStepNotDefined() throws ServiceEquipmentException {
Equipment equipment = equipmentRepository.findOne(1L);
System.err.println(equipment);
}
跟踪:
java.lang.Exception: Unexpected exception, expected<com.nordnet.testing.logic.services.exception.ServiceTestableEquipmentException> but was<java.lang.StackOverflowError>
at org.junit.internal.runners.statements.ExpectException.evaluate(ExpectException.java:28)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: java.lang.StackOverflowError
at org.h2.command.Parser.getTokenType(Parser.java:3788)
at org.h2.command.Parser.read(Parser.java:3254)
at org.h2.command.Parser.readIdentifierWithSchema(Parser.java:3135)
at org.h2.command.Parser.readTableFilter(Parser.java:1214)
at org.h2.command.Parser.readJoin(Parser.java:1532)
at org.h2.command.Parser.parseJoinTableFilter(Parser.java:1942)
at org.h2.command.Parser.parseSelectSimpleFromPart(Parser.java:1898)
at org.h2.command.Parser.parseSelectSimple(Parser.java:2045)
at org.h2.command.Parser.parseSelectSub(Parser.java:1891)
at org.h2.command.Parser.parseSelectUnion(Parser.java:1709)
at org.h2.command.Parser.parseSelect(Parser.java:1697)
at org.h2.command.Parser.parsePrepared(Parser.java:445)
at org.h2.command.Parser.parse(Parser.java:317)
at org.h2.command.Parser.parse(Parser.java:289)
at org.h2.command.Parser.prepareCommand(Parser.java:254)
at org.h2.engine.Session.prepareLocal(Session.java:561)
at org.h2.engine.Session.prepareCommand(Session.java:502)
at org.h2.jdbc.JdbcConnection.prepareCommand(JdbcConnection.java:1203)
at org.h2.jdbc.JdbcPreparedStatement.<init>(JdbcPreparedStatement.java:73)
at org.h2.jdbc.JdbcConnection.prepareStatement(JdbcConnection.java:287)
at sun.reflect.GeneratedMethodAccessor42.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.tomcat.jdbc.pool.ProxyConnection.invoke(ProxyConnection.java:126)
at org.apache.tomcat.jdbc.pool.JdbcInterceptor.invoke(JdbcInterceptor.java:108)
at org.apache.tomcat.jdbc.pool.DisposableConnectionFacade.invoke(DisposableConnectionFacade.java:81)
at com.sun.proxy.$Proxy61.prepareStatement(Unknown Source)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$5.doPrepare(StatementPreparerImpl.java:146)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:172)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl.prepareQueryStatement(StatementPreparerImpl.java:148)
at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.prepareQueryStatement(AbstractLoadPlanBasedLoader.java:241)
at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeQueryStatement(AbstractLoadPlanBasedLoader.java:185)
at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:121)
at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:86)
at org.hibernate.loader.entity.plan.AbstractLoadPlanBasedEntityLoader.load(AbstractLoadPlanBasedEntityLoader.java:167)
at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:4019)
at org.hibernate.event.internal.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:508)
at org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:478)
at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:219)
at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:278)
at org.hibernate.event.internal.DefaultLoadEventListener.doOnLoad(DefaultLoadEventListener.java:121)
at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:89)
at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1129)
at org.hibernate.internal.SessionImpl.internalLoad(SessionImpl.java:1022)
at org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:639)
at org.hibernate.type.EntityType.resolve(EntityType.java:431)
at org.hibernate.type.ComponentType.resolve(ComponentType.java:687)
at org.hibernate.loader.plan.exec.process.internal.EntityReferenceInitializerImpl.resolveEntityKey(EntityReferenceInitializerImpl.java:142)
at org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.resolveEntityKey(AbstractRowReader.java:143)
at org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.readRow(AbstractRowReader.java:94)
at org.hibernate.loader.plan.exec.internal.EntityLoadQueryDetails$EntityLoaderRowReader.readRow(EntityLoadQueryDetails.java:239)
at org.hibernate.loader.plan.exec.process.internal.ResultSetProcessorImpl.extractResults(ResultSetProcessorImpl.java:122)
at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:122)
at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:86)
at org.hibernate.loader.entity.plan.AbstractLoadPlanBasedEntityLoader.load(AbstractLoadPlanBasedEntityLoader.java:167)
at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:4019)
at org.hibernate.event.internal.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:508)
at org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:478)
at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:219)
at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:278)
at org.hibernate.event.internal.DefaultLoadEventListener.doOnLoad(DefaultLoadEventListener.java:121)
at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:89)
at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1129)
at org.hibernate.internal.SessionImpl.internalLoad(SessionImpl.java:1022)
at org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:639)
at org.hibernate.type.EntityType.resolve(EntityType.java:431)
at org.hibernate.type.ComponentType.resolve(ComponentType.java:687)
at org.hibernate.loader.plan.exec.process.internal.EntityReferenceInitializerImpl.resolveEntityKey(EntityReferenceInitializerImpl.java:142)
at org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.resolveEntityKey(AbstractRowReader.java:143)
at org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.readRow(AbstractRowReader.java:94)
at org.hibernate.loader.plan.exec.internal.EntityLoadQueryDetails$EntityLoaderRowReader.readRow(EntityLoadQueryDetails.java:239)
at org.hibernate.loader.plan.exec.process.internal.ResultSetProcessorImpl.extractResults(ResultSetProcessorImpl.java:122)
at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:122)
at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:86)
at org.hibernate.loader.entity.plan.AbstractLoadPlanBasedEntityLoader.load(AbstractLoadPlanBasedEntityLoader.java:167)
at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:4019)
at org.hibernate.event.internal.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:508)
at org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:478)
at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:219)
at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:278)
at org.hibernate.event.internal.DefaultLoadEventListener.doOnLoad(DefaultLoadEventListener.java:121)
at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:89)
at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1129)
at org.hibernate.internal.SessionImpl.internalLoad(SessionImpl.java:1022)
at org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:639)
at org.hibernate.type.EntityType.resolve(EntityType.java:431)
at org.hibernate.type.ComponentType.resolve(ComponentType.java:687)
at org.hibernate.loader.plan.exec.process.internal.EntityReferenceInitializerImpl.resolveEntityKey(EntityReferenceInitializerImpl.java:142)
at org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.resolveEntityKey(AbstractRowReader.java:143)
at org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.readRow(AbstractRowReader.java:94)
at org.hibernate.loader.plan.exec.internal.EntityLoadQueryDetails$EntityLoaderRowReader.readRow(EntityLoadQueryDetails.java:239)
at org.hibernate.loader.plan.exec.process.internal.ResultSetProcessorImpl.extractResults(ResultSetProcessorImpl.java:122)
at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:122)
at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:86)
at org.hibernate.loader.entity.plan.AbstractLoadPlanBasedEntityLoader.load(AbstractLoadPlanBasedEntityLoader.java:167)
at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:4019)
at org.hibernate.event.internal.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:508)
at org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:478)
at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:219)
at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:278)
at org.hibernate.event.internal.DefaultLoadEventListener.doOnLoad(DefaultLoadEventListener.java:121)
at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:89)
at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1129)
at org.hibernate.internal.SessionImpl.internalLoad(SessionImpl.java:1022)
at org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:639)
at org.hibernate.type.EntityType.resolve(EntityType.java:431)
at org.hibernate.type.ComponentType.resolve(ComponentType.java:687)
at org.hibernate.loader.plan.exec.process.internal.EntityReferenceInitializerImpl.resolveEntityKey(EntityReferenceInitializerImpl.java:142)
at org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.resolveEntityKey(AbstractRowReader.java:143)
at org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.readRow(AbstractRowReader.java:94)
at org.hibernate.loader.plan.exec.internal.EntityLoadQueryDetails$EntityLoaderRowReader.readRow(EntityLoadQueryDetails.java:239)
at org.hibernate.loader.plan.exec.process.internal.ResultSetProcessorImpl.extractResults(ResultSetProcessorImpl.java:122)
at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:122)
at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:86)
at org.hibernate.loader.entity.plan.AbstractLoadPlanBasedEntityLoader.load(AbstractLoadPlanBasedEntityLoader.java:167)
at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:4019)
at org.hibernate.event.internal.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:508)
at org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:478)
...
它在此选择中循环:
Hibernate: select testableeq0_.id as id1_1_0_, testableeq0_.active as active2_1_0_, testableeq0_.breakdown as breakdow3_1_0_, testableeq0_.client_id as client_i4_1_0_, testableeq0_.create_at as create_a5_1_0_, testableeq0_.equipment_key as equipmen6_1_0_, testableeq0_.esthetic_state as esthetic7_1_0_, testableeq0_.global_state as global_s8_1_0_, testableeq0_.keep_pieces as keep_pie9_1_0_, testableeq0_.local as local10_1_0_, testableeq0_.lot_number as lot_num11_1_0_, testableeq0_.mac_addr as mac_add12_1_0_, testableeq0_.manufacture_warranty_end_date as manufac13_1_0_, testableeq0_.on_warranty as on_warr14_1_0_, testableeq0_.provisionable as provisi15_1_0_, testableeq0_.provisioning_mode as provisi16_1_0_, testableeq0_.reconditionnable as recondi17_1_0_, testableeq0_.ref_catalog as ref_cat18_1_0_, testableeq0_.result_test as result_19_1_0_, testableeq0_.return_mode as return_20_1_0_, testableeq0_.rma_date as rma_dat21_1_0_, testableeq0_.serial as serial22_1_0_, testableeq0_.test_state as test_st23_1_0_, testableeq0_.testable as testabl24_1_0_, testableeq0_.type_materiel as type_ma25_1_0_, steps1_.equipment as equipmen7_0_1_, steps1_.number_step as number_s2_0_1_, steps1_.equipment as equipmen7_0_2_, steps1_.number_step as number_s2_0_2_, steps1_.html_content as html_con3_0_2_, steps1_.passed as passed4_0_2_, steps1_.selected_esthetic_state as selected5_0_2_, steps1_.label_breakdown as label_br6_0_2_, steps1_.dtype as dtype1_0_2_ from testable_equipment testableeq0_ left outer join step steps1_ on testableeq0_.id=steps1_.equipment where testableeq0_.id=?
编辑 2
设备存储库 :
@Repository
public interface EquipmentRepository extends JpaRepository<Equipment, Long> {
}
步骤存储库 :
@Repository
public interface StepRepository extends JpaRepository<AbstractStep, StepKey> {
public AbstractStep findByKey(final StepKey key);
}
@NoRepositoryBean
public interface StepBaseRepository<T extends AbstractStep> extends JpaRepository<T, StepKey> {
}
@Repository
public interface EstheticStepRepository extends StepBaseRepository<EstheticStep> {
}
@Repository
public interface FunctionalStepRepository extends StepBaseRepository<FunctionalStep> {
public List<FunctionalStep> findByLabelBreakdown(final String labelBreakdown);
}
所以我找到了答案,这是因为我认为双向关联可以在双方都是 EAGER (我是初学者(。但显然这是不可能的。所以一方不可避免地处于懒惰获取模式。