JPA - проблема проектирования сущностей
Я разрабатываю Java-приложение для настольных компьютеров и использую JPA для постоянства. У меня есть проблема, упомянутая ниже:
У меня есть две сущности:
- Страна
- город
Страна имеет следующий атрибут:
- CountryName (PK)
Город имеет следующий атрибут:
- Название города
Теперь, когда в двух разных странах может быть два города с одинаковыми именами, таблица primaryKey для города в базе данных представляет собой составной первичный ключ, состоящий из CityName
а также CountryName
,
Теперь мой вопрос: как реализовать первичный ключ
City
какEntity
на Яве
@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
Объект класса: один в country
объект и другие в cityPK
объект.
Но с другой стороны, оба необходимы:
countryName
вcityPK
объект необходим, потому что мы реализуем составные первичные ключи таким образом.countryName
вcountry
Объект необходим, потому что это стандартный способ показать связь между объектами.
Как обойти эту проблему?
2 ответа
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;
}
ИМО правильным способом решения таких проблем будет использование сгенерированного внутреннего (как правило, Long
) ID вместо естественного первичного ключа - это устраняет всю проблему. Конечно, это требует модификации схемы вашей БД, но из вашего поста я предполагаю, что это возможно.
@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
}