views:

136

answers:

1

I ran some DDL script to setup a complete country table in my database. The country table's primary key column contains the corresponding ISO code for every country.

In my JPA project I have a User entity having an embedded Address entity and this Address entity has a reference to a Country. The relationship between User and Address seems to be no problem to me, but the relationship between Address and Country. I tried to map it as a ManyToOne relationship, since many addresses can share a country.

Problem is: I annotated the iso member variable of the Country class with Id -> Now, JPA/Hibernate complains about not having set the id of the country manually. But in this case, the id is already given and set, since I imported the data once and the ISO code is unique and by db schema means declared as primary key. In this special case, there is no need for updates or inserts in the country table - the information should be read only!

Any idea what to do, so I can use my countries table without altering?

A: 

Your question is missing some details, so the following involves a lot of guessing :-)

Your Country class should look something like:

@Entity
@Immutable
@Table(name="countries")
public class Country {
  @Id
  private String isoCode;
  // all other attributes, getters / setters, etc...
}

@Immutable is a Hibernate extension to JPA standard; you don't have to put it on entity but having it will result in slightly better performance. Keep in mind that it will really make the Country immutable - you won't be able to create / update / delete countries through your application. You may want to configure cache for your Country entity as well if it's used often enough.

Your Address would have the following mapping to country:

@ManyToOne
@JoinColumn(name="country_iso_code")
private Country country;

Note the absence of "cascade" attributes - you don't need any. The final important point here is you actually need to get or load the Country instance to set it on address:

Country country = (Country) session.load(Country.class, isoCode);
// OR
Country country = (Country) session.get(Country.class, isoCode);

address.setCountry(country);
...
session.saveOrUpdate(address);

The first line above will not hit the database; use it if you know that country with such an ISO code exists. Second form will hit the database (or cache, if configured) and return NULL if country with that code does not exist.

ChssPly76