我正在使用Spring Boot与Spring Data JPA和Spring Data REST。
我有一个名为TestExection的类,它是一个具有多个TestResults的类设置。创建TestExecution时,没有创建为其设置的结果。
稍后当TestExecution运行时,会创建TestResult对象。
这些TestResult对象与TestExecution具有@OneToOne关系,在保存TestResult之前,TestReult上设置了TestExecution对象,并调用了save(TestResult)。
// Create RESULT object
TestResult testResult = new TestResult(someTestExection......);
save(testResult)
如果我通过REST拨打电话来查看testResults / 1 / testExecution,我可以看到与testResult相关的testExecution。如果我对testExecutions / 1 / testResults进行相同的调用,则返回一个空的[]。
2个问题:
1)我是否需要将新创建的TestResult对象显式设置为TestExecutions的TestResult集?
testExecution.getTestResults().add(testResult);
save(testExecution)
当我尝试这个时,会导致附加的堆栈跟踪。
Hibernate: update test_execution set description=?, owner=?, version=? where id=? and version=?
[WARNING]
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.springframework.boot.maven.AbstractRunMojo$LaunchRunner.run(AbstractRunMojo.java:478)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.StackOverflowError
at com.miw.mcb.server.model.TestExecution.hashCode(TestExecution.java:32)
at com.miw.mcb.server.model.TestResult.hashCode(TestResult.java:30)
at java.util.AbstractSet.hashCode(AbstractSet.java:126)
at org.hibernate.collection.internal.PersistentSet.hashCode(PersistentSet.java:448)
at com.miw.mcb.server.model.TestExecution.hashCode(TestExecution.java:32)
at com.miw.mcb.server.model.TestResult.hashCode(TestResult.java:30)
at java.util.AbstractSet.hashCode(AbstractSet.java:126)
at org.hibernate.collection.internal.PersistentSet.hashCode(PersistentSet.java:448)
OR
2)是否有某种方法可以设置关系,这样当TestResult设置TestExecution时,它可以链接并添加到其列表中?
TestExecution
@Data
@Entity
@Table(name = "test_execution")
//@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
public class TestExecution {
private @Id @GeneratedValue Long id;
// TODO set back to lazy
@ManyToMany(fetch = FetchType.EAGER)
//@JsonBackReference
private Set<TestResult> testResults;
// TODO set back to lazy
@ManyToMany(fetch = FetchType.EAGER)
private Set<TestSuite> testSuites;
TestResult中
@Data
@Entity
@Table(name = "test_result")
//@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
public class TestResult {
private @Id @GeneratedValue Long id;
// TODO switch back to lazy
@OneToOne(fetch = FetchType.EAGER)
//@JsonManagedReference
private TestExecution testExecution;
// TODO switch back to lazy
@OneToOne(fetch = FetchType.EAGER)
private TestSuite testSuite;
两个存储库都设置相同
TestExecutionRepository
@Repository
@Transactional
public interface TestExecutionRepository extends PagingAndSortingRepository<TestExecution, Long> {
TestResultRepository
@Repository
@Transactional
public interface TestResultRepository extends PagingAndSortingRepository<TestResult, Long> {
的AppConfig
@Configuration
@ComponentScan({ "com.miw.mcb.server.dao.repository", "com.miw.mcb.server.model" })
public class AppConfig {
}
SpringBootApp(ReactAndSpringDataRestApplication)
@SpringBootApplication
public class ReactAndSpringDataRestApplication {
public static void main(String[] args) {
SpringApplication.run(ReactAndSpringDataRestApplication.class, args);
}
}
更新:我为@ManyToOne和@OneToMany做了更新,但仍然存在TestResults
如何传播到TestExecution
的问题
感谢您对ManyToOne和OneToMany的解释。我以为我的映射不正确。
之后我在运行时获得了以下堆栈跟踪:
testExecution.getTestResults().add(testResult);
save(testExecution)
** update.setTestExecution(执行)的更新; 。execution.getResults()添加(结果); repo.save(执行);不首先保存result
**
java.lang.StackOverflowError: null
at com.miw.mcb.server.model.TestExecution.hashCode(TestExecution.java:26)
at com.miw.mcb.server.model.TestResult.hashCode(TestResult.java:35)
at java.util.AbstractSet.hashCode(AbstractSet.java:126)
at org.hibernate.collection.internal.PersistentSet.hashCode(PersistentSet.java:448)
at com.miw.mcb.server.model.TestExecution.hashCode(TestExecution.java:26)
at com.miw.mcb.server.model.TestResult.hashCode(TestResult.java:35)
at java.util.AbstractSet.hashCode(AbstractSet.java:126)
at org.hibernate.collection.internal.PersistentSet.hashCode(PersistentSet.java:448)
at com.miw.mcb.server.model.TestExecution.hashCode(TestExecution.java:26)
at com.miw.mcb.server.model.TestResult.hashCode(TestResult.java:35)
at java.util.AbstractSet.hashCode(AbstractSet.java:126)...
**为了解决这个问题,我必须使用Lombok **
实现测试结果的hasCode()函数 @EqualsAndHashCode(exclude={"id", "testExecution", "device", "testCase"})
答案 0 :(得分:2)
我认为您正在为JPA注释做出错误的选择。而且,我不明白这是如何运作的。
实际上,@ManyToMany
关系表示一种关系,其中实体的每个元素都可以与来自另一个实体的任何人相关联。您需要that的中间表。这意味着单个TestResult
可以与许多执行链接。
另一方面,您提供@OneToOne
映射,这是另一种方式,只为该对象提供另一方的一个实体实例。
您管理它的方式,看起来像您想要的@OneToMany
,这将允许TestExecution
控制testResults
集合,这意味着测试执行可能超过一个结果,但每个结果只属于一次执行。
TestExecution:
@OneToMany(fetch=FetchType.EAGER, cascade = CascadeType.ALL, mappedBy="testExecution")
private Set<TestResult> testResults;
TestResult中:
@ManyToOne(fetch=FetchType.EAGER)
@JoinColumn(name="id_test_result")
private TestExecution testExecution;
这样,您可以让TextExecution管理其TestResult集合(使用CascadeType.ALL
在保存TestExecution对象时将更改传播到集合中。)
另见: