Не думаю, что у вас есть хорошее представление о реальной модели. Дорога должна быть отдельным объектом, а не просто связью между двумя городами. Например, дорога может проходить через многие города. Также в городе может быть много дорог. Что вы описываете, так это то, что города могут быть связаны со многими городами.
Но что вы хотите описать, так это то, что между дорогами и городами существует ManyToMany
.
Простая модель JPA с однонаправленным отображением будет выглядеть следующим образом.
@Entity
public class Country {
@Id
private String name;
@Entity
public class City {
@Id
private String name;
@ManyToOne
private Country country;
@ManyToMany
private Set<Road> roads;
@Entity
public class Road {
@Id
private String name;
Чтобы сохранить карту, вы создаете графство, добавляете города, добавляете дороги и описываете, какие дороги существуют для каждого города.
tx.begin();
Country france = new Country("France");
City paris = new City("Paris");
paris.setCountry(france);
City nice = new City("Nice");
nice.setCountry(france);
City normandy = new City("Normandy");
normandy.setCountry(france);
Road r1 = new Road("R1");
Road r2 = new Road("R2");
Set<Road> roads = new HashSet<>();
roads.add(r1);
roads.add(r2);
paris.setRoads(roads);
roads = new HashSet<>();
roads.add(r2);
normandy.setRoads(roads);
roads = new HashSet<>();
roads.add(r1);
nice.setRoads(roads);
em.persist(france);
em.persist(paris);
em.persist(nice);
em.persist(normandy);
em.persist(r1);
em.persist(r2);
tx.commit();
Чтобы получить список дорог для города, вы выбираете город с его списком дорог. Чтобы увидеть, с какими городами дорога соединяется, выберите города, в которых она указана в списке дорог.
TypedQuery<City> roadsForCityQuery = em.createQuery("select c from City c join fetch c.roads join fetch c.country where c = :city", City.class);
City normandyRoads = roadsForCityQuery.setParameter("city", normandy).getSingleResult();
System.out.println("normandyRoads = " + normandyRoads);
City parisRoads = roadsForCityQuery.setParameter("city", paris).getSingleResult();
System.out.println("parisRoads = " + parisRoads);
TypedQuery<City> citiesForRoadQuery = em.createQuery("select distinct c from City c join fetch c.roads road join fetch c.country where road = :road", City.class);
List<City> r1Cities = citiesForRoadQuery.setParameter("road", r1).getResultList();
System.out.println("r1Cities = " + r1Cities);
List<City> r2Cities = citiesForRoadQuery.setParameter("road", r2).getResultList();
System.out.println("r2Cities = " + r2Cities);
Это дает следующие результаты:
normandyRoads = City(name=Normandy, roads=[Road(name=R2)])
parisRoads = City(name=Paris, roads=[Road(name=R1), Road(name=R2)])
r1Cities = [City(name=Nice, roads=[Road(name=R1)]), City(name=Paris, roads=[Road(name=R1), Road(name=R2)])]
r2Cities = [City(name=Normandy, roads=[Road(name=R2)]), City(name=Paris, roads=[Road(name=R1), Road(name=R2)])]