Я разрабатываю Настольное приложение Java и использую JPA для персистентности. Мне упомянули проблему ниже:
У меня есть два объекта:
Страна имеет следующий атрибут:
Город имеет следующий атрибут:
Теперь как может быть два города с тем же именем в двух разных странах, primaryKey для таблицы City в datbase является составным первичным ключом, состоявшим из 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
и показать эти отношения в вышеупомянутом коде, я добавил a country
переменная в City
класс.
Но затем у нас есть дублирующиеся данные (countryName
) сохраненный в двух местах в City
объект класса: один в country
возразите и другой в cityPK
объект.
Но с другой стороны, оба необходимы:
countryName
в cityPK
объект необходим, потому что мы реализуем составные первичные ключи таким образом.
countryName
в country
объект необходим, потому что это - стандартный способ показать relashionship между объектами.
Как обойти эту проблему?
ИМО, правильным способом решения таких проблем было бы использование сгенерированного внутреннего (обычно 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
}
countryName
в CityPK
следует пометить как доступный только для чтения с помощью @Column (insertable = false, updatable = false )
и оба countryName
должны быть сопоставлены с одним и тем же столбцом (с использованием свойства 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;
}