如何使用 Hibernate Projection 检索复杂的 class 及其成员?
How to retrieve a complex class and its members using Hibernate Projection?
我有一个 class 如下,需要使用 Hibernate 从数据库中检索。
问题是我的 class 有多个成员,其中大部分是 class,我该如何检索它们?
@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 及其所有课程、其经销商和经销商汽车列表。
我的预测如下,但它没有return任何东西。
...
.setProjection(Projections.projectionList()
.add(Projections.property("friends.cars").as("cars")
...
如果高性能不是问题,那么您应该让 Hibernate 完成他的工作。
只需使用实体的吸气剂即可。
例如:
Student student1 = session.get(Student.class, 1L);
List<Course> courses = student1.getCourses();
Dealer dealer = student1.getDealer();
Set<Car> cars = dealer.getCars();
因为你有一个课程列表和一组汽车,你可以简单地在一个查询中获取整个图表:
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<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));
我不确定你是否可以使用 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 以获得结果。这只是一个开始的提示,您可以根据您的要求进行修改。我希望这会奏效。 :)
我有一个 class 如下,需要使用 Hibernate 从数据库中检索。 问题是我的 class 有多个成员,其中大部分是 class,我该如何检索它们?
@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 及其所有课程、其经销商和经销商汽车列表。
我的预测如下,但它没有return任何东西。
...
.setProjection(Projections.projectionList()
.add(Projections.property("friends.cars").as("cars")
...
如果高性能不是问题,那么您应该让 Hibernate 完成他的工作。 只需使用实体的吸气剂即可。 例如:
Student student1 = session.get(Student.class, 1L);
List<Course> courses = student1.getCourses();
Dealer dealer = student1.getDealer();
Set<Car> cars = dealer.getCars();
因为你有一个课程列表和一组汽车,你可以简单地在一个查询中获取整个图表:
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<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));
我不确定你是否可以使用 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 以获得结果。这只是一个开始的提示,您可以根据您的要求进行修改。我希望这会奏效。 :)