【问题标题】:Get single element from JPA nested OneToMany relationship从 JPA 嵌套的 OneToMany 关系中获取单个元素
【发布时间】:2017-07-19 09:07:23
【问题描述】:

我有那些实体,它不是来自真实代码,但我认为这并不重要。

    @Entity
    public class Country{

       private String name;
       //other fields with getters and setters
       @OneToMany
       private List<City> cites;


    }

    @Entity
    public class City {

       private String name;
        //other fields with getters and setters
       @OneToMany
       private List<Employee> emps;//list size could be millions


    }

     @Entity
     public class Employee {

        private String name;
        //other fields with getters and setters

       @OneToMany
       private List<Cars> cars;// list size could be 1000

    }


     @Entity
    public class Car {
      private String name;

      @ManyToOne
      private Employee emp;
    }

我想获得单个 Car 实体,但也需要像这样的其他数据(国家、城市、员工)

1 个国家,1 个城市,1 个员工,1 个汽车(我选择了哪个 ID)

所以当我从国家加入 jpa 时,就像

select c from Country c 
 inner join c.cites ci 
 inner join ci.emps em
  inner join ci.cars car where car.id = ?

我获得了 Country(包括所有城市)的所有数据。

我应该怎么做才能得到 1 Country,1 City, 1 Employee, 1 Car.

如果用一个 jpa 查询无法做到这一点,请建议其他方式。

所有的关系都是双向的和惰性的。

I tried this way. 
1)select car by id. then get Id of employee from car. 
2)select Employee by id - but at this point Employee data are nulls -

我认为这是因为从 Car 到 Employee 的 ManyToOne 是懒惰的。你怎么看?

【问题讨论】:

    标签: java hibernate jpa jpql querydsl


    【解决方案1】:

    只需选择您想要的其他实体:

    select c, ci, em, car from Country c 
    inner join c.cites ci 
    inner join ci.emps em
    inner join ci.cars car where car.id = ?
    

    或者,由于您的关联是双向的,请选择汽车:它的员工将有一个 ManyToOne,它的城市会有一个 ManyToOne,它的国家会有一个 ManyToOne:

    select car from Car car where car.id = ?
    

    或者干脆

    em.find(Car.class, carId);
    

    现在你可以做

    car.getEmployee().getCity().getCountry()
    

    【讨论】:

    • 非常感谢。对于这两种解决方案,我都必须这样做。 emp.setCars(Collections.sigltonlist(car)) city.setEmps(Collections.singletonList(emp)) country.setCiyes(Collections.singletonList(city)) 否则在json序列化期间,所有惰性集合都会填充数百万数据。当 ManyToOne 是 Lazy 时,第二个解决方案也不起作用(在这种情况下数据为空)
    • 不,不,不要那样做。修改托管实体将自动使更改在数据库中持久化。您真的不想删除该国家/地区的所有城市等。即使该实体不受管理,这也只会显示您的应用程序中的设计问题。您序列化为 JSON 的不是一个有城市的国家。它是查询的结果,其中包含国家、城市等的部分视图。只需创建一个适当的类,其中包含您真正想要序列化的实际数据,并且由您的 REST 资源返回。
    • 谢谢,我认为在选择实体后没有管理 - 这就是为什么我没有在数据库中获得更新。但我明白你在说什么。因此,在您看来,使用包含单个 Employee 的单个城市返回 Country 是错误的。等等……
    • 是的。您正在修改国家的城市属性应该代表的含义:国家的所有城市。您返回的不应该是一个国家/地区。
    【解决方案2】:

    如果所有关系都是双向的,那么我建议从 Car 开始,然后向上获取层次结构。

    select c from Car car 
      inner join fetch car.emp emp
      inner join fetch emp.city city
      inner join fetch city.country country 
    where car.id = ?
    

    请记住在您错过的所有联接中添加 fetch

    【讨论】:

    • 非常感谢。但我也必须做 emp.setCars(Collections.sigltonlist(car)) city.setEmps(Collections.singletonList(emp)) country.setCiyes(Collections.singletonList(city)) 然后只从 Spring 控制器返回县对象否则在 json序列化所有惰性集合都填充了数百万个数据
    猜你喜欢
    • 1970-01-01
    • 2014-05-01
    • 1970-01-01
    • 2013-11-09
    • 2021-05-03
    • 1970-01-01
    • 2016-02-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多