Reputation: 2619
OK, so today I tried a basic Hibernate tutorial and I'm struggling to make it behave how I want.
This is a simple snippet, assume all other fields/methods are defined (e.g. id etc.)
@Entity
@Table(name = "CITIES")
public static class City {
@ManyToOne
@OnDelete(action = OnDeleteAction.CASCADE)
private Country country;
}
@Entity
@Table(name = "COUNTRIES")
public static class Country {
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private Set<City> cities;
}
The above solution utilizes an (automatically created) association table - COUNTRY_CITIES
, but
this does work only in one way - i.e. I see country's cities (when I select one), but I don't see a city's country (when I select a city).
So what should I do to make cities see their country?
I can add a @JoinColumn(name = "COUNTRY_ID")
to the Country.cities
field and it works in two ways.
But I don't like to add columns to city's table from country's code.
So I added the @JoinColumn
to the City.country
field and it didn't work.
So - how to make the association work in 2 ways w/o an association table??
OK, to be precise: I used the above code add feed the DB with this objects:
Country germany = new Country("Germany", new HashSet<>(asList(
new City("Berlin"),
new City("Hamburg")
)));
.. and viewed the DB. It looked like this:
table COUNTRIES_CITIES (note, I didn't declare it; Hibernate does automatically)
COUNTRIES_ID CITIES_ID
1 1
1 2
table COUNTRIES
ID NAME
1 Germany
table CITIES (note I didn't declare the COUNTRY_ID column! Hibernate again..)
ID NAME COUNTRY_ID
1 Berlin null
2 Hamburg null
And that's it. Fetching the country gives me the cities, fetching the city gives me null country.
If I add a @JoinColumn
to the Country
class, then the a column is appended to the CITIES
table and fetching works two ways.
Upvotes: 2
Views: 3319
Reputation: 169
step 1: Add mappedBy at OneToMany side.
@OnetoMany(mappedBy="users")
private List<Address> address;
step 2: Add JoinColumn at ManyToOne Side.
@ManytoOne
@JoinColumn("userId")
private User user;
Upvotes: 0
Reputation: 624
After reading your edit problem is clear.
The way you are adding cities and associating with Country...
Country germany = new Country("Germany", new HashSet<>(asList(
new City("Berlin"),
new City("Hamburg")
)));
If you do this then City does not have a country. No where you setting City's country property. ie. city.country = germany;
In a bidirectional relationship you cannot rely on JPA or your provider to entirely manage object persistence for you.
So This is what you need to do..
Country germany = new Country("Germany");
City berlin = new City("Berlin");
City Hamburg = new City("Hamburg");
berlin.country = germany;
hamburg.country = germany;
germany.cities = new HashSet<>(asList(berlin, hamburg));
germany.saveOrUpdate(); // or whichever definition you use
Now in the db you Cities Table will have correct country ids.
Also it is recommended, since this is a bidirectional relationship, that you use the mappedBy
attribute in your @OneToMany
relationship. Using it you are telling JPA that cities is the inverse side of the Country 1-n City
relationship.
Upvotes: 3
Reputation: 1177
Have you tried using the mappedBy
property?
@OneToMany(mappedBy="country", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private Set<City> cities;
For an explanation, look here: Can someone please explain mappedBy in hibernate?
Upvotes: 2