7

I am developing a Java Desktop Application and using JPA for persistence. I have a problem mentioned below:

I have two entities:

  • Country
  • City

Country has the following attribute:

  • CountryName (PK)

City has the following attribute:

  • CityName

Now as there can be two cities with same name in two different countries, the primaryKey for City table in the datbase is a composite primary key composed of CityName and CountryName.

Now my question is How to implement the primary key of the City as an 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;
   }

Now as we know that the relationship from Country to City is OneToMany and to show this relationship in the above code, I have added a country variable in City class.

But then we have duplicate data(countryName) stored in two places in the City class' object: one in the country object and other in the cityPK object.

But on the other hand, both are necessary:

  • countryName in cityPK object is necessary because we implement composite primary keys in this way.

  • countryName in country object is necessary because it is the standard way of showing relashionship between objects.

How to get around this problem?

4

2 回答 2

7

countryNameinCityPK应该标记为只读 using@Column(insertable = false, updatable = false)并且两个countryNames 应该映射到同一列(使用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;
   }
于 2010-04-01T19:17:52.837 回答
3

IMO 处理此类问题的正确方法是使用生成的内部(通常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
}
于 2010-04-02T08:35:55.753 回答