JPA / Hibernate, @OneToMany и ограничения (Oracle) - PullRequest
2 голосов
/ 26 августа 2011

У меня есть следующий сценарий:

@Entity
class A {

  @Id
  @GeneratedValue
  private long dbId;

  @OneToMany ( cascade = CascadeType.ALL )
  @JoinColumn( name = "A_ID", referencedColumnName = "DBID" )
  Set<C> setOfCs;

}

@Entity
class B {

  @Id
  @GeneratedValue
  private long dbId;

  @OneToMany ( cascade = CascadeType.ALL )
  @JoinColumn( name = "B_ID", referencedColumnName = "DBID" )
  Set<C> setOfCs;

}

@Entity
class C {

    @Id
@GeneratedValue
private long dbId;

}

Таблица C создается с двумя столбцами A_ID и B_ID в качестве внешних ключей для A.DBID и B.DBID соответственно. В моем случае это не имеет большого смысла, так как каждый элемент C связан либо с A, либо с (xor) B, но не с обоими одновременно (оба отношения - «один ко многим», а не «многие ко многим»).

Есть ли способ иметь одинаковые таблицы (что нормально) без ограничения внешнего ключа для A_ID и B_ID? Когда я устанавливаю A-> C, Oracle жалуется, что C.B_ID не установлен.

Спасибо

Маттео

Ответы [ 2 ]

1 голос
/ 26 августа 2011

Почему вы не используете @JoinTable?он удалит любой внешний ключ из таблицы C.

@OneToMany(cascade = CascadeType.ALL,fetch=FetchType.LAZY,orphanRemoval=true)
@JoinTable(name = "A_B_TABLE", joinColumns = { @JoinColumn(name = "A_ID") },      inverseJoinColumns = { @JoinColumn(name = "DB_ID") })
public Set<C> getSetOfCs() {
    return setOfCs;
}

и, между прочим, не будет аннотировать элементы, вместо этого сделайте это на своих получателях.

0 голосов
/ 26 августа 2011

Единственный способ, которым я могу придумать, - это заставить оба отношения через общий класс, к которому C может иметь внешний ключ.

Самый простой способ сделать это - ввести класс X, который будет суперклассом A и B и будет иметь свойства dbId и setOfCs. В таблице С будет столбец X_ID.

В качестве альтернативы, сделать C абстрактным и ввести подклассы Ca и Cb, чтобы экземпляры A всегда ссылались на экземпляры Ca, а экземпляры от B до Cb. Каждому из Ca и Cb потребуется только один внешний ключ. Это может быть очень неудобно для использования, хотя; среди прочего, это означало бы, что вы никогда не сможете перенести экземпляр C из A в B.

Если у вас не было возможности вводить какие-либо базовые классы, вы можете применить закон Уилера и штукатурку к слою косвенного обращения, комбинируя оба вышеуказанных подхода. Создайте абстрактный класс X и присвойте ему свойства dbId и setOfCs из A и B; C затем имеет фантомное отношение ManyToOne к X, и у этой таблицы есть соответствующий внешний ключ. Создайте два конкретных подкласса X, Xa и Xb, каждый из которых имеет отношение OneToOne с экземпляром A или B соответственно, причем эти экземпляры A и B имеют соответствующие отношения OneToOne, указывающие в другом направлении.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...