2012-03-14 3 views
1

Если я запрос в SQL:Почему соединение JPA возвращает слишком много результатов?

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 вернется 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, и вы увидите, что она не нагружает профессор и его ученик. Он загружает профессора.

Во-вторых: объект должен представлять данные в базе данных. Он не должен представлять результат запроса. Таким образом, коллекция студентов в лице профессора всегда является коллекцией всех студентов профессора.

Чтобы сделать то, что вы хотите, у вас есть несколько вариантов:

  1. select p, s from Profesor inner join p.students s...: это возвращает массив, содержащий найденный Profesor и найденную студента.
  2. если ассоциация является двунаправленной: select s from Profesor p inner join p.students s ...: это загрузит студент, и он ссылается на его профессор
  3. при использовании Hibernate, который нарушает спецификацию JPA в этой области: select p from Profesor inner join fetch p.students...: Выборки марка зимует загрузить профессор и его ученик в одном запросе. Но так как вы добавили предложение where для ученика, оно загружает только подходящих учеников профессора.

Обратите внимание, что третье решение является очень опасным, и я бы не советовал его использовать. Во-первых, потому что это недействительно JPQL. И что еще более важно, поскольку код, получающий объект Professor, загруженный таким запросом, ожидает, что Professor.getStudents() вернет всех студентов профессора, а не только один из них. Таким образом, он может отображать ложные результаты или изменять сбор и приводить к некогерентности в базе данных.

+0

выберите p, s from Profesor internal join p.students s ... Жестокий тест. –

Смежные вопросы