如何使用Hibernate Projection检索复杂的类及其成员?

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

@Entity public class Student { @Id long id; String name; String fname; @OneToMany List courses; @ManyToOne Dealer dealer; ... } @Entity public class Dealer { @Id long id; String name; @OneToMany(fetch = FetchType.LAZY, mappedBy = "cr.dealer", cascade = CascadeType.ALL) Set cars = new HashSet(0); .. } 

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

我的预测如下,但它不会返回任何内容。

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

因为您有一个课程列表和一组汽车,您只需在一个查询中获取整个图表:

 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(); 
  // Projection is not needed, Hibernate will load child values as shown below Student student = session.get(Student.class); List 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("br", "br", JoinType.INNER_JOIN); criteria.createAlias("bc", "bc", 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)); 

如果高性能不是一个问题,那么你应该让Hibernate完成他的工作。 只需使用你实体的getter。 举个例子:

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

我不确定您是否可以使用QueryOver,但这对于这类任务来说非常容易。

 Student student = null; Dealer dealer = null; Course course = null; Car car = null; var myStudent = Session.QueryOver(() => 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()) .List().AsQueryable(); 

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