2014-09-24 5 views
1

У меня есть три стола, Member, Address и Mem_Addr. Member и Address объекты сопоставлены/связаны Mem_Addr стол. Многим многим.Hibernate Mapping - соединительный стол без @Id

У меня есть следующие объекты для Member и Address:

@Entity 
@Table (name="Member") 
public class Member{ 

    @Id //.... 
    private Integer mem_id; 

    @OneToOne 
    @JoinTable  (name = "Mem_Addr", 
      joinColumns = @JoinColumn(name = "addr_id"), 
     inverseJoinColumns = @JoinColumn(name = "mem_id")) 
    Set<Address> addresses = new HashSet<Address>; 
    ... 
} 

Mem_Addr стол (Это не связано сущностей).

addr_id // (PK) Sequence 
mem_id // (FK to mem_id in Member table) 
.... 
.... 

Address субъект.

@Entity 
@Table(name="Address") 
public class Address { 

    private String addr_id; // Foreign Key to addr_id in Mem_addr table 
    private String address1; 
    ... 
} 

У меня нет ID в Address таблицы/сущности. (Пожалуйста, не спрашивайте меня о дизайне. Его нельзя изменить сейчас.)

Поэтому, когда я загружаю участников, я хочу загрузить все адреса для этого члена.

Какое решение?

Edit: Подробнее ...

В принципе некоторые Member s будет иметь новую запись в таблице Mem_Addr. Для каждой записи в таблице Mem_addr будет запись в таблице Address.

Чтобы получить адрес члена, мне нужно обратиться к Mem_Addr. Mem_Addr имеет addr_id в качестве первичного и Адрес имеет addr_id как внешний ключ.

+1

Есть ли addr_id в объекте Address, потому что я вижу в сущности Mem, которую вы вызываете? – Rika

+0

@ Рика, ты прав. Я ошибся. Исправленный. –

+0

Я думаю, что вы, вероятно, можете подключиться без идентификаторов, но у него должна быть встроенная аннотация, см. Здесь http://stackoverflow.com/questions/767277/hibernate-and-no-pk – Rika

ответ

1

К сожалению, нет никакого способа обойти, Hibernate требует, чтобы ваш стол имел первичный ключ.

Вы можете проверить this document.

1

Вы уверены, что стол Mem_Addr - это много-ко многим, а не один-ко-многим? Я не вижу, как один Address может быть связан с более чем одной Member ...

Предполагая, что это на самом деле один-ко-многим, сопоставить Address сущность в оба Mem_Addr и Address таблицы через @SecondaryTable аннотацию, как описано в Hibernate Mapping Two Tables to One Class, отображая идентификатор до Mem_Addr.addr_id, Member через Mem_Addr.mem_id, и все остальное через другие поля в Address.

Я не сделал этого, но я считаю, что это будет работать:

@Entity 
@Table(name = "Address") 
@SecondaryTable(name = "Mem_Addr", pkJoinColumns={ 
    @PrimaryKeyJoinColumn(name="addr_id" referencedColumnName="addr_id") 
}) 
class Address { 
    @Id 
    @Column 
    private String addr_id; 

    .... 
} 
+0

Возможно.Поскольку в домене страхования несколько клиентов могут иметь одинаковый адрес. Хорошо, если я предполагаю, что это будет @OneToMany, но ваше решение неясно. Можете ли вы уточнить? –

+0

Я этого не делал (к счастью, у меня всегда были схемы, которые были более разумными, чем то, за чем вы застряли), но вы должны иметь возможность использовать аннотацию @SecondaryTable для этого, как описано в http: // stackoverflow .com/вопросы/1667918/гибернации-отображение-две таблицы к одному классу. – Tim

+0

Кроме того, я согласен с тем, что в реальном мире возможно наличие нескольких 'Member' для одного' Address'. Но я не думаю, что это возможно в вашей схеме базы данных (вам нужно было бы создать один объект «Адрес» для каждого объекта «Member», хотя значения этого «Адреса» были бы одинаковыми), поэтому, надеюсь, вам будет разрешено изменить эту схему в какой-то момент в будущем. – Tim

1

Хорошо так, вставки и обновления не нужны, следующие (в теории), возможно, следует работать:

@Entity 
@Table(name = "Address") 
class Address { 

@Id 
private AddressKey id; 

public void setId(AddressKey id) { 
this.id = id; 
} 

public void getId() { 
return id; 
} 
} 

и

@Embeddable 
class AddressKey implements Serializable { 
    @Column(name = "addr_id") 
    private String addrId; //also the underscore should be deleted 

    @Column(name = "address_1") 
    private String address1; 



    } 

Это временное решение найдено для таблиц, которые не имеют первичные ключи. Как вы можете видеть, это в значительной степени делает фальшивый идентификатор.

+0

Если мы не беспокоимся о вставках и обновлениях, то зачем беспокоиться с @Embeddable? Просто сопоставьте 'addr_id' как @Id и сделайте с ним. (Кроме того, 'address1' не является частью первичного ключа для таблицы, поэтому я не уверен, почему вы включили его в @Embeddable ...) – Tim

+0

Но как вы сопоставляете таблицу Address to Members. Между этими двумя сторонами нет никакой связи. Это может быть простая вещь .. .. вы меня. Я новичок в Hibernate :-) –

+1

Для записи, однако, я думаю, что это плохое решение преднамеренно отобразить объект Hibernate, который нельзя использовать для пишите в базу данных, даже если вы считаете, что вам не нужна эта способность. Скорее всего, вы в какой-то момент, и даже если вам действительно не нужны они в производстве, что делать, если вы хотите написать некоторые тестовые данные в фиктивную базу данных для использования в модульных тестах? Я думаю, что принятие такого подхода было бы ошибкой, когда другие подходы также будут работать и не приходят с этими недостатками, но мы все можем сделать свой собственный выбор, так что это ваш звонок. – Tim