2010-07-24 8 views
8

Mam problem z konfigurowaniem mapowań jpa dla niektórych podmiotów. Mam element nadrzędny zdefiniowany jak poniżej.jpa hibernacji złożony klucz obcego mapowania

@Entity 
@Table(name="EIF_INSTANCE_HDR") 
public class InstanceEntity implements Serializable{ 

private static final long serialVersionUID = 1L; 

@Id 
@GeneratedValue(generator="eif_inst_gen") 
@SequenceGenerator(name="eif_inst_gen",sequenceName="EIF_INSTANCE_SEQ") 
@Column(name = "EAIH_ID") 
private Long eaihid; 
@Column(name = "EAD_ID") 
private Long eadid; 

@OneToMany(targetEntity=InstanceNotifyEntity.class, mappedBy="instance",fetch=FetchType.EAGER, cascade = CascadeType.ALL) 
private List<InstanceNotifyEntity> userDetails = new ArrayList<InstanceNotifyEntity>(); 
} 

Mam następnie podmiot podrzędny w/kluczu złożonym oraz klucz obcy do klucza pierwotnego tabeli w następujący sposób:

@Entity 
@Table(name="EIF_INST_NOTIFIED") 
public class InstanceNotifyEntity implements Serializable{ 

private static final long serialVersionUID = 1L; 

@Id 
@ManyToOne 
@JoinColumn(name="EAIH_ID", referencedColumnName="EAIH_ID") 
private InstanceEntity instance; 

@Id 
@Column(name="USER_ID") 
private Long userId; 
@Column(name="COMMENT_TXT") 
private String commentText; 
} 

wiem podmiot dziecko jest niepoprawna, ale nie jestem pewien, jak ustawić to mieć złożoną PK. Wiem, że muszę ustawić klasę PK, ale nie jestem pewien, jak to zrobić, gdy jedno pole jest obcym kluczem do klasy nadrzędnej. A kiedy to jest skonfigurowane, w jaki sposób rodzic odwołuje się do elementu podrzędnego?

Każda pomoc jest doceniana.

+0

Zobacz http://stackoverflow.com/questions/2562746/jpa-entity-design-problem/ 2563009 # 2563009 – axtavt

Odpowiedz

12

Jest to regulowane przez JPA 2 spec sekcja 2.4.1, "Klucze podstawowe odpowiadające tożsamościom pochodnym". Ta sekcja zawiera dwa przykłady bezpośrednio odnoszące się do twojego problemu.

Jak opisano w specyfikacji, istnieją dwa sposoby reprezentują klucza podmiotu dziecka w tym przypadku:

  • @IdClass
  • @EmbeddedId

Oto szorstki szkic drogi EmbeddedId. Wybrałem EmbeddedId arbitralnie, ale wybór pomiędzy IdClass i EmbeddedId jest znaczący. Możesz wybrać inaczej.

// Child entity's composite primary key 
@Embeddable 
public class InstanceNotifyEntityId implements Serializable { 
    Long eaihId; 
    Long userId; 
} 

// Child entity 
@Entity 
@Table(name="EIF_INST_NOTIFIED") 
public class InstanceNotifyEntity implements Serializable { 
    @AttributeOverrides({ 
     @AttributeOverride(name="userId", column = @Column(name="USER_ID")) 
     @AttributeOverride(name="eaihId", column = @Column(name="EAIH_ID")) 
    }) 
    @EmbeddedId 
    InstanceNotifyEntityId id; 

    @MapsId("eaihId") 
    @ManyToOne 
    InstanceEntity instance; 

    // ... 
} 

Jednostka dominująca musi jedną zmianę: atrybut mappedByuserDetails powinno być "id.eaihId". Myślę, że to wszystko, ale nie używałem jeszcze takich obiektów wcześniej. Mogło coś przeoczyć ... proszę napisać, jeśli widzisz błędy.

+0

Dzięki, działa to w przeważającej części. Niestety nie używam jpy 2.0, więc adnotacja @MapsId nie jest dostępna. Mam to działa dla insertów, usuwając zależności kaskadowych z obiektu userDetails elementu nadrzędnego. Tak więc jestem zobowiązany do wstawienia każdego elementu podrzędnego po utrzymaniu elementu nadrzędnego, ale na razie jest to wykonalne. – broschb

+0

@broschb Czego używasz? –

+0

jpa 1.0 spec. Obecnie jestem zobowiązany do korzystania z jboss 4.2.3, moim zdaniem jpa 2.0 nie działa na tym serwerze aplikacji, przynajmniej nie bez wymiany wielu bibliotek. – broschb

0

Miałem również do czynienia z tą samą kwestią i podążałem za tą odpowiedzią, ale nie zapisuje ona elementu podrzędnego z elementem nadrzędnym. Oto zmiany, które wprowadziłem i działają dobrze. Dokonać zmian poniżej -

// Child entity's composite primary key class 

public class InstanceNotifyEntityId implements Serializable { 

    @Column(name = "USER_ID") 
    Long userId; 

    @JoinColumn(name = "EAIH_ID") 
    @ManyToOne 
    InstanceEntity instance 
} 

// Child entity which contain composite primary key as a EmbeddedId, 
// no need to define any relationship here as we already define 
// the relationship in composite key class. 

@Entity 
@Table(name = "EIF_INST_NOTIFIED") 
public class InstanceNotifyEntity implements Serializable { 

    @EmbeddedId 
    InstanceNotifyEntityId id; 
} 


// Parent entity (parent entity mappedby should be your composite 
// key class instance.child class object which already have the 
// join column mapping with "EAID_ID") 

@Entity 
@Table(name = "EIF_INSTANCE_HDR") 
public class InstanceEntity implements Serializable { 

    @OneToMany(mappedBy = "id.instance,fetch=FetchType.EAGER, cascade = CascadeType.ALL) 
    private List<InstanceNotifyEntity> userDetails = new ArrayList<InstanceNotifyEntity>(); 
} 

Podczas zapisywania podmiotem dominującym ustawić obiektu nadrzędnego do klucza kompozytowego jak id.setInstance(parent entire obj)