Отображение базы данных только для чтения с отношением "многие-ко-многим" без таблицы соединений
У меня есть вопрос, похожий на @ManyToMany без таблицы соединений (устаревшая база данных) с дополнительной проблемой.
У меня есть две таблицы A
и B
-
A
с помощью первичного ключа с несколькими столбцами (ID
и ID2
)
-
B
с помощью первичного ключа с несколькими столбцами (ID
и ID3
)
Строка в A
может ссылаться на несколько строк в B
(B.ID = A.ID
), а строка в B
может ссылаться на несколько строк в A
.
EDIT: база данных - это устаревшая база данных только для чтения, которую я не могу изменить. Мне не нужно сопоставлять отношения с JPA (я мог бы просто сделать это в своей логике программы с дополнительными выделениями), но было бы неплохо.
Это в основном отношение "многие ко многим" без таблицы соединений. Поскольку, поскольку для связанного вопроса, я просто должен прочитать таблицы, я пробовал с двумя отношениями один-ко-многим в обоих классах.
Дополнительная проблема, которую я испытываю, заключается в том, что оба ID
, используемые для соединения, не являются первичным ключом.
У меня есть следующие классы:
@Entity
@Table( name = "A" )
@IdClass( PrimaryKeysA.class )
public class A {
@Id
@Column( name = "ID", insertable = false, updatable = false, columnDefinition = "char" )
private String id;
@Id
@Column( name = "ID2", insertable = false, updatable = false )
private int id2;
@OneToMany( cascade = CascadeType.ALL )
@JoinColumn( name = "ID", columnDefinition = "char", referencedColumnName = "ID" )
private Set< B > setOfBs;
}
@Entity
@Table( name = "B" )
@IdClass( PrimaryKeysB.class )
public class B {
@Id
@Column( name = "ID", insertable = false, updatable = false, columnDefinition = "char" )
private String id;
@Id
@Column( name = "ID3", insertable = false, updatable = false )
private int id3;
@OneToMany( cascade = CascadeType.ALL )
@JoinColumn( name = "ID", columnDefinition = "char", referencedColumnName = "ID" )
private Set< A > setOfAs;
}
Спящий режим генерирует следующую ошибку:
Exception while preparing the app : referencedColumnNames(ID) of package.B referencing package.A not mapped to a single property
Я действительно не получаю сообщение: B.id
ссылается на одно свойство в A
(A.id
).
EDIT: по запросу:
public class PrimaryKeysA implements Serializable {
private static final long serialVersionUID = 1L;
private int id1;
private int id2;
// getters/setters/equals/hashcode
}
PrimaryKeysB
похож на id3 вместо id2. Оба класса A
и B
являются упрощенными (анонимизированными) примерами.
Ответы
Ответ 1
Вы можете создать представление, которое будет действовать как таблица соединений:
CREATE VIEW AJOINB AS
SELECT A.ID as AID, A.ID2 as AID2, B.ID as BID, B.ID3 as BID3
FROM A JOIN B ON A.ID = B.ID
И затем сопоставьте его в JPA как ManyToMany с AJOINB в качестве таблицы соединений.
Если A.ID2 и B.ID3 были уникальны сами по себе, вам даже не понадобилось бы сопоставлять A.ID и B.ID в JPA beans.
Ответ 2
Можете ли вы поделиться некоторыми примерами записей из таблиц?
Проблема очень ясна. Для любого отношения "один-много" на "одной" стороне должна быть только одна запись, которая может быть однозначно идентифицирована. Здесь, я думаю, поскольку id не уникален, существует несколько записей.
Вы можете попытаться использовать @JoinColumns и добавить оба столбца, чтобы однозначно идентифицировать сущность на "одной" стороне.
@OneToMany
@JoinColumns({
@JoinColumn(name="yourID1", referencedColumnName="yourID1"),
@JoinColumn(name="yourid2", referencedColumnName="yourid2")
})
Я предполагаю, что у вас есть следующие данные.
таблица A:
id2 c1 id
100 content1 1000
101 content2 1001
таблица B:
id3 s1 id
100 content1 1000
101 content2 1000
102 content3 1001
103 content4 1001
Здесь id2 и id3 уникальны. A.id уникален, но b.id не является; типичный сценарий OneToMany.
Если я сопоставляю A-B с использованием A.id и B.id, тогда это становится одним ко многим, где A (100) может ссылаться на B (100, 101), так как id 1000
Это будет хорошо работать, я думаю. Но если вам нужно отобразить из B в A, используя те же столбцы (как указано в вопросе), это не будет работать, поскольку одна сторона (B) имеет дубликаты.
Я правильно понимаю ваш вопрос?