【问题标题】:How to retrieve a complex class and its members using Hibernate Projection?如何使用 Hibernate Projection 检索复杂类及其成员?
【发布时间】:2015-06-23 15:37:30
【问题描述】:

我有一个类如下,需要使用 Hibernate 从数据库中检索。 问题是我的班级有多个成员,其中大多数是班级,我该如何检索它们?

@Entity
public class Student {
  @Id
  long id;
  String name;
  String fname;
  @OneToMany
  List<Course> courses;
  @ManyToOne
  Dealer dealer;
  ...
}

@Entity
public class Dealer {
   @Id
   long id;
   String name; 
   @OneToMany(fetch = FetchType.LAZY, mappedBy = "cr.dealer", cascade = CascadeType.ALL)
   Set<Car> cars = new HashSet<Cars>(0);
   ..

}

我需要检索学生 id 1 及其所有课程、经销商和经销商汽车列表。

我的投影如下,但它没有返回任何东西。

  ...
    .setProjection(Projections.projectionList()

    .add(Projections.property("friends.cars").as("cars")
    ...

【问题讨论】:

    标签: java sql hibernate orm hibernate-criteria


    【解决方案1】:
        // Projection is not needed, Hibernate will load child values as shown below
    
        Student student = session.get(Student.class);
        List<Course> courses = student.getCourses();
        Dealer dealer = student.getDealer();
    
        //  If u want records only where child records are present, u can use LEFT_OUTER_JOIN
    
        Criteria criteria = getHibernateSession().createCriteria(Student.class);
        criteria.createAlias("Course", "Course", JoinType.LEFT_OUTER_JOIN);
    
        // If u want to use Projections for performance, u have to add each and every column in projection
    
        Criteria criteria = getHibernateSession().createCriteria(A.class);
        criteria.createAlias("b", "b", JoinType.INNER_JOIN);
        criteria.createAlias("b.r", "b.r", JoinType.INNER_JOIN);
        criteria.createAlias("b.c", "b.c", JoinType.LEFT_OUTER_JOIN);
        ProjectionList projectionList = Projections.projectionList();
        projectionList.add(Projections.groupProperty("column1"));
        projectionList.add(Projections.property("column2"));
        projectionList.add(Projections.property("column3"));
        criteria.setProjection(projectionList);
        criteria.setResultTransformer(Transformers.aliasToBean(Table.class));
    

    【讨论】:

    【解决方案2】:

    因为您有一个课程列表和一组汽车,您可以简单地在单个查询中获取整个图表:

    select s
    from Student s
    left join fetch s.courses
    left join fetch s.dealer d
    left join fetch d.cars
    where s.id = :id
    

    由于您要获取两个集合,因此该查询将生成笛卡尔积,因此您需要确保所选子集合没有太多条目。

    如果您不想遇到笛卡尔积,您可以简单地运行以下查询:

    select s
    from Student s
    left join fetch s.courses
    left join fetch s.dealer d
    where s.id = :id
    

    然后您访问dealer.cars 以使用单独的查询获取该集合:

    Student s = ...;
    s.getDealer().getCars().size();
    

    【讨论】:

    【解决方案3】:

    如果高性能不是问题,那么您应该让 Hibernate 完成他的工作。 只需使用实体的吸气剂。 例如:

    Student student1 = session.get(Student.class, 1L);
    List<Course> courses = student1.getCourses();
    Dealer dealer = student1.getDealer();
    Set<Car> cars = dealer.getCars();
    

    【讨论】:

      【解决方案4】:

      我不确定你是否可以使用 QueryOver,但对于这类任务来说它会很容易。

      Student student = null;
      Dealer dealer = null;
      Course course = null;
      Car car = null;
      
      var myStudent = Session.QueryOver<Student>(() => student)
      .Left.JoinQueryOver(() => student.courses, () => courses)
      .Left.JoinQueryOver(() => student.dealer, () => dealer)
      .Left.JoinQueryOver(() => dealer.cars, () => car)
      .SelectList(list => list
        .Select(() => student.Name)
        .Select(() => student.Age)
        .Select(() => courses.Description)
        .Select(() => dealer.locaiton)
        .Select(() => car.Model))
        .TransformUsing(Transformers.AliasToBean<StudentModel>())
        .List<StudentModel>().AsQueryable();
      

      创建一个 StudentModel DTO 以获得结果。这只是一个开始的提示,您可以根据需要进行修改。我希望这会奏效。 :)

      【讨论】:

        猜你喜欢
        • 2013-11-28
        • 2015-07-10
        • 2015-11-06
        • 2011-07-16
        • 2014-03-29
        • 2017-10-24
        • 1970-01-01
        • 1970-01-01
        • 2011-07-20
        相关资源
        最近更新 更多