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

时间:2015-04-17 00:16:51

标签: java sql hibernate orm hibernate-criteria

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

@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")
    ...

4 个答案:

答案 0 :(得分:4)

    // 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));

答案 1 :(得分:1)

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

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();

答案 2 :(得分:0)

如果不考虑高性能,那么你应该让Hibernate完成他的工作。 只需使用你实体的getter。 例如:

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

答案 3 :(得分:0)

我不确定您是否可以使用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以获得结果。这只是一个开始的提示,您可以根据您的要求进行修改。我希望这会奏效。 :)