I am using Spring Boot with Spring Data JPA and Spring Data REST.
I have a class called TestExection, it is a class setup to have multiple TestResults. When a TestExecution is created there are no results created to set for it.
Later when the TestExecution is run TestResult objects are created.
These TestResult objects have a @OneToOne relation to the TestExecution and prior to saving a TestResult the TestExecution object is set on the TestResult and the save(TestResult) is called.
// Create RESULT object
TestResult testResult = new TestResult(someTestExection......);
save(testResult)
If I make a call via REST to see the testResults/1/testExecution I can see the testExecution associated with the testResult. If I make the same call to testExecutions/1/testResults it returns a empty [].
2 questions:
1) Do I need to expclicitly set the newly created TestResult object into the TestExecutions's TestResult Set?
testExecution.getTestResults().add(testResult);
save(testExecution)
When I try this it causes the attached stack trace.
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) Is there some way to have it setup with a relationship so that when TestResult sets a TestExecution it can be linked and added to its list?
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;
Both Repositories are setup the same
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);
}
}
UPDATE: I made the updates for @ManyToOne and @OneToMany but there is still the problem of how the TestResults
are propagated to TestExecution
Thank your for the explanation on ManyToOne and OneToMany. I thought I had the mapping incorrect.
After that I got the following stack trace when running:
testExecution.getTestResults().add(testResult);
save(testExecution)
** Update for result.setTestExecution(execution); execution.getResults().add(result); repo.save(execution); without saving result
first **
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)...
** To fix this I had to implement the hasCode() function for test result with Lombok **
@EqualsAndHashCode(exclude={"id", "testExecution", "device", "testCase"})