为什么JPA加入会返回太多结果? [英] Why does JPA join return too many results?

查看:62
本文介绍了为什么JPA加入会返回太多结果?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我使用SQL查询:

If I query in SQL:

select * from Profesor
inner join Estudiantes on Profesor.id = Estudiante.id
where Profesor.nombre = 'juan'
  and Estudiante.nombre = 'jose'

此查询返回教授和学生.一名教授和一名学生.只是胡安教授,何塞是学生.

This query return the profesor and the student. One profesor and one student. Just Profesor Juan with Jose as Student.

然后,如果我在JPA中查询:

Then if I Query in JPA:

select p from Profesor p
inner join p.estudiantes e
where p.nombre = juan
  and e.nombre = jose.

JPA会给Juan教授和 all 个学生,而不仅仅是我想要的那个,而profesor.estudiantes将列出与 all 个学生一起的列表.

JPA will return profesor Juan with all the students not just the one I wanted and profesor.estudiantes will have the list with all the students.

我的类型是:

class Profesor{
    private List<Estudiante> estudiantes;
}

class Estudiante{
    String matricula;
}

对不起,我用西班牙语编写代码.我只是弄清楚了.

Sorry I code in spanish. I just figure out this.

我不清楚我是否很清楚我的问题,请告诉我.

I dont know if I were clear on my question, please tell me.

推荐答案

您需要了解两件事.

首先:当您说Select p from Profesor时,JPA仅从Profesor表中选择列,并返回一个Profesor实例,其中包含尚未加载的学生集合.第一次实际访问集合时,它会延迟加载.当加载集合时,它已经忘记了您用来加载教授的查询.它加载的是教授学生的集合.既然教授有很多学生,那么他们就成了所有人的罪魁祸首.初始查询类似于

First: when you say Select p from Profesor, JPA only selects the columns from the Profesor table, and returns a Profesor instance containing a collection of students that is not loaded yet. It's loaded lazily the first time you actually access the collection. And when it loads the collection, it has forgotten which query you used to load the professor. What it loads is the collection of students of the professor. And since a professor has many students, it ;oads them all. The initial query is similar to

select p.* from Profesor inner join ...

在SQL中执行它,您将看到它不会加载教授及其学生.它只会加载一位教授.

Execute it in SQL, and you'll see that it doesn't load a professor and its student. It only loads a professor.

第二个:实体应该代表数据库中的数据.它不应该代表查询的结果.因此,教授实体中的学生集合始终是教授中所有学生的集合.

Second: an entity is supposed to represent the data in the database. It isn't supposed to represent the result of a query. So, the collection of students in a Professor entity is always the collection of all the students of the professor.

要做您想做的事,您有几种选择:

To do what you want, you have several choices:

  1. select p, s from Profesor inner join p.students s...:这将返回一个包含找到的教授和找到的学生的数组.
  2. 如果关联是双向的:select s from Profesor p inner join p.students s ...:这将加载学生,并引用其教授
  3. 如果使用的是Hibernate,则违反了该领域的JPA规范:select p from Profesor inner join fetch p.students...:获取操作使hibernate在单个查询中加载教授及其学生.但是,由于您在学生上添加了where子句,因此只会加载与教授匹配的学生.
  1. select p, s from Profesor inner join p.students s...: this will return an array containing the found profesor, and the found student.
  2. if the association is bidirectional: select s from Profesor p inner join p.students s ...: this will load the student, and it references its professor
  3. if using Hibernate, which violates the JPA spec in this area: select p from Profesor inner join fetch p.students...: the fetch makes hibernate load the professor and its students in a single query. But since you added a where clause on the student, it only loads the matching students of the professor.

请注意,第三种解决方案非常危险,我不建议您使用它.首先,因为它不是有效的JPQL.而且更重要的是,由于通过此类查询加载到Professor实体的代码期望Professor.getStudents()将返回教授的所有学生,而不仅是其中之一.因此,它可能会显示错误的结果,或者修改集合并导致数据库中的不一致.

Note that the third solution is a very dangerous one, and I wouldn't advise using it. First because it's not valid JPQL. And more importantly, because the code getting a Professor entity loaded by such a query expects that professor.getStudents() will return all the students of the professor, and not just one of them. It could thus display false results, or modify the collection and cause incoherences in the database.

这篇关于为什么JPA加入会返回太多结果?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆