2010-04-01 20 views
7

Zajmuję się tworzeniem aplikacji Java Desktop i używanie JPA do utrwalania. Mam problem wymienione poniżej:JPA - Problem z projektem jednostki

Mam dwa podmioty:

  • Kraj
  • Miasto

Kraj ma następujący atrybut:

  • COUNTRYNAME (PK)

City posiada następujące atrybuty:

  • cityname

Teraz jak nie może być dwóch miast o tej samej nazwie w dwóch różnych krajach, primaryKey na stole miasta w datbase jest kompozytowa klucz podstawowy składa z CityName i CountryName.

Teraz moje pytanie brzmi: Jak wdrożyć klucz podstawowy z City jako Entity w Javie

@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; 
    } 

Teraz jak wiemy, że relacje z Country do City jest OneToMany i pokazać to w powyższym kodzie dodałem zmienną country w klasie City.

Ale wtedy mamy zduplikowane dane (countryName) przechowywanych w dwóch miejscach na obiektu City klasy: jedna w obiekcie country i innych w obiekcie cityPK.

Ale z drugiej strony, obie są konieczne:

  • countryName w cityPK obiekt jest konieczne, ponieważ realizujemy klucze złożone w ten sposób.

  • countryName w country przedmiotu jest konieczna, ponieważ jest to standardowy sposób pokazano relashionship między przedmiotami.

Jak obejść ten problem?

Odpowiedz

7

countryName w CityPK powinny być oznaczone tylko do odczytu za pomocą @Column(insertable = false, updatable = false) i oba countryName s powinny być przypisane do tej samej kolumnie (za pomocą name właściwość):

@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

Czy jest to standardowy sposób radzenia sobie z tego typu problemami? Czy ten problem jest powszechny w WZP? –

+0

@ Yatendra: Tak, jest to standardowy sposób (jeśli nie używasz kluczy zastępczych, jak sugeruje Peter). – axtavt

3

IMO właściwy sposób radzić sobie z takimi kwestiami byłoby używanie wygenerowanego wewnętrznego (zwykle Long) identyfikatora zamiast naturalnego klucza podstawowego - eliminuje to cały problem. Oczywiście wymaga to modyfikacji twojego schematu DB, ale z twojego postu zakładam, że jest to możliwe.

@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

Następnie myślę, że nie mogę użyć "id" w równości metoda równości. Poprawny? –

+0

@ Yatendra Dlaczego nie? Dwa miasta o tej samej nazwie, ale innym kraju muszą mieć różne identyfikatory. Musisz tylko upewnić się, że nie wstawiłeś tego samego miasta z tego samego kraju dwa razy w tabeli. Może to być wymuszone przez wyzwalacz bazy danych lub przez przechwytywacz Hibernate. –

+0

Nie można użyć 'id' w' equals() ', ponieważ' id' jest generowany przez bazę danych. I nie będą dostępne, dopóki obiekt nie zostanie utrwalony. Zobacz "Gavin Kinga" Java Persistence with Hibernate ", patrz dyskusja na temat klucza biznesowego i klucza zastępczego. – Ram