1

Я использую Spring Boot с данными Spring Data JPA и Spring Data REST.Невозможно настроить отношения @ManyToMany и @OneToOne правильно для двунаправленных данных Spring JPA и Spring REST

У меня есть класс под названием TestExection, это установка класса, чтобы иметь несколько тестовых результатов. Когда создается TestExecution, для его создания не создаются результаты.

Позже, когда выполняется TestExecution, создаются объекты TestResult.

Эти объекты TestResult имеют отношение @OneToOne к тесту TestExecution и до сохранения TestResult объект TestExecution установлен в TestResult и вызывается сохранение (TestResult).

// Create RESULT object 
    TestResult testResult = new TestResult(someTestExection......); 
    save(testResult) 

Если я сделать вызов через REST, чтобы увидеть TestResults/1/testExecution Я могу видеть testExecution, связанный с TestResult. Если я делаю тот же вызов testExecutions/1/testResults, он возвращает пустой [].

2 вопросы:

1) Мне нужно установить expclicitly вновь созданный объект 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) 
    

ИЛИ

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); 
} 
} 

UPDATE: Я сделал обновления для @ManyToOne и @OneToMany, но есть еще проблема, как TestResults являются до TestExecution

Благодарим вас за объяснение ManyToOne и OneToMany. Я думал, что неверное отображение.

После этого я получил следующую трассировку стеки при работе:

testExecution.getTestResults().add(testResult); 
save(testExecution) 

** Обновление для result.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)... 

** Чтобы исправить это, я должен был реализовать функцию hasCode() для результата теста с Ломбками **

@EqualsAndHashCode(exclude={"id", "testExecution", "device", "testCase"}) 
+0

Вы должны установить владельца сторону отношений, предоставив 'mappedBy' атрибут. При сохранении вам необходимо настроить каскады в зависимости от ваших требований. – Vaelyr

ответ

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) ,

Смотрите также:

+0

Спасибо за объяснение ManyToOne и OneToMany. Я думал, что неверное отображение. У меня все еще есть вопрос, хотя с тех пор я продолжаю получать тот же результат. Как «TestResult» распространяется в объект «TestExecution»? Должен ли я сохранить «TestResult», а затем взять этот объект и добавить его в набор «TestExecution»? Или это должно быть сделано при сохранении «TestResult» с установкой «TestExecution» на объекте «TestResult»? – ALM

+0

Ex: Сохранение с 'TestExecution' установить на' TestResult' все еще оставляет пустой результат, установленный на «» TestExecution сохранить (TestResult) ли я тогда сделать вызов, чтобы добавить это в 'TestExecution' testExecution.getTestResults () .add (TestResult); save (testExecution) – ALM

+0

Похоже, мне придется реализовать свой собственный hashCode(), чтобы остановить дубликаты. Я попробовал базовый, но это не сработало, поэтому я буду работать над этим. Спасибо – ALM

 Смежные вопросы

  • Нет связанных вопросов^_^