如果我在SQL中查询:
select * from Profesor
inner join Estudiantes on Profesor.id = Estudiante.id
where Profesor.nombre = 'juan'
and Estudiante.nombre = 'jose'
此查询返回profesor和学生。一位教授和一位学生。只有胡安教授和何塞为学生。
然后,如果我在JPA中查询:
select p from Profesor p
inner join p.estudiantes e
where p.nombre = juan
and e.nombre = jose.
JPA将使用 all 返回profesor Juan,而不仅仅是我想要的学生,profesor.estudiantes
将列出所有学生。
我的类型是:
class Profesor{
private List<Estudiante> estudiantes;
}
class Estudiante{
String matricula;
}
抱歉,我用西班牙语编码。我只想弄清楚这一点。
我不知道我的问题是否清楚,请告诉我。
答案 0 :(得分:2)
你需要了解两件事。
首先:当你说Select p from Profesor
时,JPA只选择Profesor表中的列,并返回一个Profesor实例,其中包含尚未加载的学生集合。第一次实际访问该集合时,它会被懒惰地加载。当它加载集合时,它忘记了用于加载教授的查询。它载入的是教授的学生集合。由于教授有很多学生,所以他们都是这样。初始查询类似于
select p.* from Profesor inner join ...
在SQL中执行它,你会发现它没有加载教授及其学生。它只会加载教授。
第二:实体应该代表数据库中的数据。它不应该代表查询的结果。因此,教授实体中的学生集合始终是教授所有学生的集合。
要做你想做的事,你有几个选择:
select p, s from Profesor inner join p.students s...
:这将返回一个包含找到的profesor和找到的学生的数组。select s from Profesor p inner join p.students s ...
:这将加载学生,并引用其教授select p from Profesor inner join fetch p.students...
:fetch使hibernate在单个查询中加载教授及其学生。但是既然你在学生身上添加了一个where子句,它只会加载教授的匹配学生。请注意,第三种解决方案非常危险,我不建议使用它。首先是因为它不是有效的JPQL。更重要的是,因为获得由这样的查询加载的教授实体的代码期望教授.getStudents()将返回教授的所有学生,而不仅仅是其中之一。因此,它可能会显示错误的结果,或修改集合并导致数据库中的不连贯。