2010-04-01 16 views
7

Ich entwickle eine Java Desktop-Anwendung und JPA für Persistenz verwenden. Ich habe ein Problem unten erwähnt:JPA - Entity Design Problem

Ich habe zwei Entitäten:

  • Land
  • Stadt

Land hat das folgende Attribut:

  • Country (PK)

City hat das folgende Attribut:

  • Cityname

Jetzt, da es in zwei verschiedenen Ländern ist die primaryKey für City-Tabelle in der datbase ein Verbundprimärschlüssel bestehen zwei Städte mit dem gleichen Namen sein kann von CityName und .

Nun meine Frage ist, wie die Primärschlüssel der City als 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; 
    } 

Jetzt zu implementieren, wie wir wissen, dass die Beziehung Country-CityOneToMany ist und dies zu zeigen, Beziehung in dem obigen Code, habe ich eine country Variable in City Klasse hinzugefügt.

Aber dann haben wir doppelte Daten (countryName) an zwei Stellen im Objekt City Klasse gespeichert: ein im country Objekt und andere im cityPK Objekt.

Aber auf der anderen Seite, beide sind notwendig:

  • countryName in cityPK Objekt notwendig ist, weil wir zusammengesetzte Primärschlüssel in dieser Art und Weise umzusetzen.

  • countryName in country Objekt ist notwendig, weil es die Standardmethode ist, relacshipeship zwischen Objekten zu zeigen.

Wie umgehen Sie dieses Problem?

Antwort

7

countryName in CityPK sollte schreibgeschützt @Column(insertable = false, updatable = false) mit markiert und beide countryName s sollte auf der gleichen Spalte zugeordnet werden (mit name Eigenschaft):

@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

Ist dies eine Standardmethode zur Behandlung dieser Art von Problem? Ist dieses Problem in JPA häufig? –

+0

@Yatendra: Ja, es ist ein Standardweg (wenn Sie keine Ersatzschlüssel verwenden, wie Peter es vorschlägt). – axtavt

3

IMO die richtige Art und Weise mit solchen Fragen zu befassen wäre eine generierte interne ID (typischerweise Long) anstelle eines natürlichen Primärschlüssels zu verwenden - dies beseitigt das ganze Problem. Natürlich erfordert dies eine Änderung Ihres DB-Schemas, aber ich gehe davon aus, dass dies möglich ist.

@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

Dann denke ich, dass ich "ID" nicht in der Equals-Methode für die Gleichheit verwenden kann. Richtig? –

+0

@Yatendra Warum nicht? Zwei Städte mit demselben Namen, aber einem anderen Land müssen unterschiedliche IDs haben. Sie müssen nur sicherstellen, dass Sie die gleiche Stadt des gleichen Landes nicht zweimal in die Tabelle einfügen. Dies könnte durch einen DB-Trigger oder durch einen Hibernate-Interceptor erzwungen werden. –

+0

Sie können 'id' nicht in' equals() 'verwenden, da' id' von der Datenbank generiert wird. Und wird nicht verfügbar sein, bis das Objekt dauerhaft ist. Siehe "Java Persistence with Hibernate" von Gavin King, siehe Diskussion zu Business Key und Surrogate Key. – Ram