Двойная самоссылка внутри одной и той же сущности с использованием дополнительной таблицы соединений

#java #jpa

#java #jpa

Вопрос:

Я хочу создать объект с двойной самоссылкой, используя дополнительную таблицу соединений. Таким образом, я попробовал следующее :

 @Entity 
@Table(name = "entity_a", schema="schema_a")
public class EntityA{
@Id 
@Column(name = "id", unique = true, nullable = false)
private UUID id = UUID.randomUUID();
//skipped source code...
@OneToOne(fetch = FetchType.LAZY)
@JoinTable(name = "origin_child",
      joinColumns = 
        { @JoinColumn(name = "origin_id", referencedColumnName = "id", nullable = false)},
      inverseJoinColumns = 
        { @JoinColumn(name = "child_id", referencedColumnName = "id", nullable = false)})
  private EntityA child;

@OneToOne(fetch = FetchType.LAZY)
@JoinTable(name = "origin_child",
      joinColumns = 
        { @JoinColumn(name = "child_id", referencedColumnName = "id", nullable = false)},
      inverseJoinColumns = 
        { @JoinColumn(name = "origin_id", referencedColumnName = "id", nullable = false)})
  private EntityA origin;
  //skipped source code...
}
 

При запуске моего кода я получаю следующую ошибку : org.hibernate.boot.spi.InFlightMetadataCollector$DuplicateSecondaryTableException: Table with that name [origin_child] already associated with entity

Таким образом, я попытался удалить origin поле, EntityA и это сработало. Теперь я пытаюсь найти способ объединить мои EntityA.id и EntityA.origin_id поверх уже существующих origin_child.child_id и. origin_child.origin_id Любая идея, как я могу этого добиться. Любое альтернативное или лучшее решение более чем приветствуется.

Обновить :

Я попробовал @JoinColumn альтернативу следующим образом :

 @OneToOne(fetch = FetchType.LAZY, mappedBy = "child")
private EntityA origin;

@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "child_id", referencedColumnName = "id", nullable = true)
private EntityA child;
 

Теперь при попытке обновить как исходные, так и дочерние экземпляры :

 child.setOrigin(origin);
entityARepository.save(child);
origin.setChild(child);
entityARepository.save(origin); 
 

Я получаю java.lang.StackOverflowError из-за бесконечной рекурсии.

Любая работа, пожалуйста?

Комментарии:

1. Может быть, потому, что два описания origin_child таблицы отличаются. В одном случае значение child_id является обнуляемым, в другом — origin_id обнуляемым, на самом деле ни то, ни другое не должно быть обнуляемым, поэтому либо установите все 4 nullable атрибута false равными, либо просто удалите все 4 атрибута.

2. Вопрос: Зачем вам это нужно @JoinTable ? Почему они не просто простые @JoinColumn ?

3. @Andreas Я пытался @JoinColumn , но я получаю ошибку StackOverflow во время выполнения

4. @Andreas Я исправил nullable=false все 4 атрибута, по-прежнему получая то же сообщение об исключении, что и упомянутое выше.

5. Теперь вам пора прочитать руководство о том, как это сделать @OneToOne , например, см. Статью Baeldung » Взаимно однозначные отношения в JPA «. Короче говоря, используйте только @JoinColumn один из них, а не оба.