composite PK/FK
danjourno Dec 29, 2005 12:58 AMI am trying to build a entity structure where I have a country table that uses ISO 3166 country codes as their PK, and a region table which also uses ISO3166 codes as a composite PK. For example.. a record in the country_region table that refers to New South Wales in Australia will have a primary key of:
country_code_1 = AU (FK value for country table)
region_code = NS
So in summary I have a CountryRegion table that has a many(regions) to one(country) relationship with a Country table. The key for the CountryRegion table is a composite of the country code and the region code.
I have referred to the wiki for this but am still a bit stuck on how to make this work.
I'll paste my code below.. If anyone could please look over an give me pointers as to where I'm going wrong I would be very grateful.
I have a Country entity, a CountryRegion entity, and an embeddable PK object called CountryRegion
The CountryRegion entity:
import java.io.Serializable; import javax.persistence.EmbeddedId; import javax.persistence.Entity; import javax.persistence.*; //import java.util.List; @Entity @Table(name = "country_region") public class CountryRegion implements Serializable { java.lang.String name; java.lang.String description; CountryRegionPK pk; public CountryRegion() { } @EmbeddedId @AttributeOverrides({ @AttributeOverride(name = "regionCode", column = @Column(name = "region_code")), @AttributeOverride(name = "country", column = @Column(name="country_code_1")) }) public CountryRegionPK getPk() { return pk; } public void setPk(CountryRegionPK pk) { this.pk = pk; } @Column(name = "description") public java.lang.String getDescription() { return description; } public void setDescription(java.lang.String description) { this.description = description; } @Column(name = "name") public java.lang.String getName() { return name; } public void setName(java.lang.String name) { this.name = name; } }
The Country entity:
import java.io.Serializable; import javax.persistence.*; @Entity @Table(name="country") public class Country implements Serializable { java.lang.String countryCode1; java.util.List<Location> locations; java.util.List<CountryRegion> countryRegion; @Id @Column(name="country_code_1") public java.lang.String getCountryCode1() { return countryCode1; } public void setCountryCode1(java.lang.String countryCode1) { this.countryCode1 = countryCode1; } @OneToMany(fetch=FetchType.LAZY,mappedBy="country") public java.util.List<Location> getLocations() { return locations; } public void setLocations(java.util.List<Location> locations) { this.locations = locations; } @OneToMany(fetch=FetchType.LAZY,mappedBy="country") public java.util.List<CountryRegion> getCountryRegion() { return countryRegion; } public void setCountryRegion(java.util.List<CountryRegion> countryRegion) { this.countryRegion = countryRegion; } }
The Embedded primary key object:
import javax.persistence.Embeddable; @Embeddable public class CountryRegionPK implements java.io.Serializable{ private Country country; private String regionCode; public CountryRegionPK() { super(); // TODO Auto-generated constructor stub } public CountryRegionPK(String regionCode, Country country) { this.regionCode = regionCode; this.country = country; } public Country getCountry() { return country; } public void setCountry(Country country) { this.country = country; } public String getRegionCode() { return regionCode; } public void setRegionCode(String regionCode) { this.regionCode = regionCode; } public int hashCode() { return (int) country.hashCode() + regionCode.hashCode(); } public boolean equals(Object obj) { if (obj == this) return true; if (!(obj instanceof CountryRegionPK)) return false; if (obj == null) return false; CountryRegionPK pk = (CountryRegionPK) obj; return pk.country.equals(country) && pk.regionCode.equals(regionCode); }
An example of a referring entity (Location)
import java.io.Serializable; import javax.persistence.*; @Entity @Table(name="location") public class Location implements Serializable{ java.lang.Integer locationId; java.lang.String city; java.lang.String postalCode; CountryRegion countryRegion; Country country; java.util.Date creationDate; @Column(name="creation_date",nullable=false,updatable=false) public java.util.Date getCreationDate() { return creationDate; } public void setCreationDate(java.util.Date creationDate) { this.creationDate = creationDate; } @Id(generate = GeneratorType.AUTO) @Column(name="location_id") public java.lang.Integer getLocationId() { return locationId; } public void setLocationId(java.lang.Integer locationId) { this.locationId = locationId; } @Column(name="city") public java.lang.String getCity() { return city; } public void setCity(java.lang.String city) { this.city = city; } @ManyToOne @JoinColumn(nullable=false, name="country_code_1") public Country getCountry() { return country; } public void setCountry(Country country) { this.country = country; } @ManyToOne(fetch=FetchType.EAGER) @JoinColumns ( {@JoinColumn(nullable=false, name="region_code"), @JoinColumn(nullable=false, name="country_code_1")}) public CountryRegion getCountryRegion() { return countryRegion; } public void setCountryRegion(CountryRegion countryRegion) { this.countryRegion = countryRegion; } @Column(name="postal_code") public java.lang.String getPostalCode() { return postalCode; } public void setPostalCode(java.lang.String postalCode) { this.postalCode = postalCode; } }