JPA - проблема проектирования сущностей - PullRequest
7 голосов
/ 01 апреля 2010

Я занимаюсь разработкой настольного Java-приложения и использую JPA для постоянного хранения. У меня есть проблема, упомянутая ниже:

У меня есть две сущности:

  • Страна
  • Город

Страна имеет следующий атрибут:

  • CountryName (PK)

Город имеет следующий атрибут:

  • CityName

Теперь, когда в двух разных странах могут быть два города с одинаковыми именами, таблица primaryKey для города в базе данных - это составной первичный ключ, состоящий из CityName и CountryName.

Теперь мой вопрос: как реализовать первичный ключ City как Entity в 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;
   }

Теперь, когда мы знаем, что отношение от Country до City равно OneToMany, и чтобы показать это отношение в приведенном выше коде, я добавил переменную country в класс City.

Но тогда у нас есть дубликаты данных (countryName), хранящиеся в двух местах в объекте City class ': одно в объекте country и другое в объекте cityPK.

Но с другой стороны, необходимы оба:

  • countryName в cityPK объект необходим, потому что мы реализуем составные первичные ключи таким образом.

  • countryName в country объект необходим, потому что это стандартный способ отображения отношений между объектами.

Как обойти эту проблему?

Ответы [ 2 ]

7 голосов
/ 01 апреля 2010

countryName в CityPK следует пометить только для чтения, используя @Column(insertable = false, updatable = false), и оба countryName s должны быть сопоставлены с одним и тем же столбцом (используя свойство name):

  @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;
   }
3 голосов
/ 02 апреля 2010

По мнению IMO, правильным способом решения таких проблем будет использование сгенерированного внутреннего (обычно Long) идентификатора вместо естественного первичного ключа - это устраняет всю проблему. Конечно, это требует изменения схемы вашей БД, но из вашего поста я предполагаю, что это возможно.

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