2010-04-01 12 views
7

Sto sviluppando un'applicazione Java Desktop e utilizzando JPA per la persistenza. Ho un problema di seguito indicate:JPA - Problema di progettazione di entità

Ho due entità:

  • Paese
  • Città

Paese ha il seguente attributo:

  • CountryName (PK)

City ha il seguente attributo:

  • CityName

Ora, come ci possono essere due città con lo stesso nome in due paesi diversi, la primaryKey per la tavola Città in datbase è una chiave primaria composta composta di CityName e CountryName.

Ora la mia domanda è come implementare la chiave primaria della City come Entity in Java

@Entity 
    public class Country implements Serializable { 
     private String countryName; 

     @Id 
     public String getCountryName() { 
      return this.countryName; 
     } 
    } 

    @Entity 
    public class City implements Serializable { 
      private CityPK cityPK; 
      private Country country; 

      @EmbeddedId 
      public CityPK getCityPK() { 
       return this.cityPK; 
      } 
    } 


    @Embeddable 
    public class CityPK implements Serializable { 
     public String cityName; 
     public String countryName; 
    } 

Ora, come sappiamo che il rapporto Country-City è OneToMany e mostrare questo relazione nel codice precedente, ho aggiunto una variabile country nella classe City.

Ma poi abbiamo i dati duplicati (countryName) memorizzati in due punti nell'oggetto City di classe: uno nell'oggetto country e altri nell'oggetto cityPK.

Ma d'altra parte, sono entrambi necessari:

  • countryName in cityPK oggetto è necessario perché applichiamo chiavi primarie composite in questo modo.

  • countryName in country l'oggetto è necessario perché è il modo standard di mostrare la relazione tra gli oggetti.

Come risolvere questo problema?

risposta

7

countryName in CityPK dovrebbe essere di sola lettura utilizzando @Column(insertable = false, updatable = false) ed entrambi countryName s dovrebbe essere mappati alla stessa colonna (utilizzando name proprietà):

@Entity 
    public class City implements Serializable { 
      @EmbeddedId 
      private CityPK cityPK; 

      @ManyToOne 
      @JoinColumn(name = "countryName") 
      private Country country; 
    } 


    @Embeddable 
    public class CityPK implements Serializable { 
     public String cityName; 

     @Column(name = "countryName", insertable = false, updatable = false) 
     public String countryName; 
    } 
+0

Si tratta di un metodo standard per gestire questo tipo di problema? Questo problema è comune in JPA? –

+0

@Yatendra: Sì, è un modo standard (se non si usano le chiavi surrogate, come suggerisce Peter). – axtavt

3

IMO il modo corretto di affrontare tali problemi sarebbe per utilizzare un ID interno generato (in genere Long) anziché una chiave primaria naturale, si elimina l'intero problema. Ovviamente, ciò richiede una modifica del tuo schema DB, ma dal tuo post presumo che ciò sia possibile.

@Entity 
public class City implements Serializable { 
    private Long id; 

    private String name; 
    private Country country; 

    @Id 
    @GeneratedValue 
    @Column(name = "CITY_ID") 
    public Long getId() { 
     return this.id; 
    } 
    private void setId(Long id) { 
     this.id = id; 
    } 

    // more getters, setters and annotations 
} 
+0

Quindi penso che non possa usare 'id' nel metodo equals per l'uguaglianza. Corretta? –

+0

@ Yatendra Perché no? Due città con lo stesso nome ma un altro paese devono avere ID diversi. Devi solo assicurarti di non inserire due volte la stessa città dello stesso paese nella tabella. Questo potrebbe essere applicato da un trigger DB o da un intercettore Hibernate. –

+0

Non si può usare 'id' in' equals() 'perché 'id' è generato dal database. E non sarà disponibile finché l'oggetto non verrà mantenuto. Fai riferimento a "Persistenza di Java con Hibernate" di Gavin King, vedi la discussione sulla chiave aziendale e la chiave surrogata. – Ram

Problemi correlati