I have the following problem in java/spring.
I tried to simplify at maximum my problem with a more concrete case. To summarize, we have a class Country and each country is linked to many City. Each City is linked to another with an intermediate class Road.
I implemented it that way (see below) but this does not satisfact me because we have a redundancy in the Road object, linked to the Country by its cities and by its country attribute (for the example, let's assume we don't care for the duplicates, ie the Road Paris-Lyon and the Road Lyon-Paris).
Another precision, we don't have cross countries. All the roads and the cities under the country belong to the same country.
public class Country implements Serializable {
...
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "country")
private List<City> cities;
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "country")
private List<Road> roads;
}
public class City implements Serializable {
...
@ManyToOne(optional = false)
@JoinColumn(name = "countryId", referencedColumnName = "id")
private Country country;
}
public class Road implements Serializable {
// Unicity by the corresponding 3 items countryId, cityFromId and cityToId
...
@ManyToOne(optional = false)
@JoinColumn(name = "countryId", referencedColumnName = "id")
private Country country;
@ManyToOne(optional = false)
@JoinColumn(name = "cityFromId", referencedColumnName = "id")
private City cityFrom;
@ManyToOne(optional = false)
@JoinColumn(name = "cityToId", referencedColumnName = "id")
private City cityTo;
}
To avoid this duplicate reference, we could imagine to take off the reference to the Country class in the Road class, but this would imply to add the references @OneToMany or the Road in the class City. We would then be on a cyclic reference because of the fact that the Road is linking 2 cities (see below).
public class Country implements Serializable {
...
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "country")
private List<City> cities;
}
public class City implements Serializable {
...
@ManyToOne(optional = false)
@JoinColumn(name = "countryId", referencedColumnName = "id")
private Country country;
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "cityFrom")
private List<Road> cityFromRoad;
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "cityTo")
private List<Road> cityToRoad;
}
public class Road implements Serializable {
// Unicity by the corresponding 3 items countryId, cityFromId and cityToId
...
@ManyToOne(optional = false)
@JoinColumn(name = "cityFromId", referencedColumnName = "id")
private City cityFrom;
@ManyToOne(optional = false)
@JoinColumn(name = "cityToId", referencedColumnName = "id")
private City cityTo;
}
Could you please help me to find a better way to make my model?
Thanks a lot!


one-to-manyare seldom used in the OO manner .Just map the "many-to-one" side is enough. In case when you need to get those "many" entities , you can use query to get them rather than getting theoneand navigate to those "many" in order to get them.