Запрос сущности с фильтрами по атрибуту OneToMany дает странный результат - PullRequest
2 голосов
/ 06 декабря 2011

Я использую EclipseLink в течение 9 месяцев и пока проблем нет.Поскольку мне нужно запросить объект с атрибутом OneToMany, все наоборот.Это дает мне странный результат.Я упростила свои сущности до максимума, но проблема остается.

Я объясню свою потребность, которая очень проста: у меня есть две сущности: Лицо, которое имеет двунаправленную связь с адресом.У человека потенциально может быть несколько адресов, но адрес принадлежит одному и тому же человеку.

В классах это дает:

@Entity
public class Person implements Serializable {

    @Id
    private Long id;

    @OneToMany(mappedBy = "person", fetch = FetchType.LAZY)
    private Set<Address> addresses;

    // Getter and setter
      ...
}


@Entity
public class Address implements Serializable {

    @Id
    private String idAddress;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "idPerson", referencedColumnName = "idPerson")
    private Person person;

    // Getter and setter
    ...
}

Я хочу запросить у человека их адреса.Все это с некоторыми условиями на человека и адрес.Мой упрощенный запрос:

select pers FROM Person pers join pers.addresses address
                 where pers.matricule=:matricule                    
                 and address.date=:dateContract

Когда я его выполняю, я получаю нужного человека, но со всеми адресами, связанными (с внешним ключом) с этим человеком.Даже адреса, которые не соответствуют условию dateContract.

Кажется, это проблема, связанная с использованием фильтрации по атрибуту oneToMany в моем запросе.Проблема будет решена, если я сделаю несколько запросов, но это даст низкую производительность, поскольку у меня есть несколько таких запросов.Я попытался с oneToMany в нетерпеливой инициализации и с подсказкой запроса выборки-соединения, но у меня тот же результат.

Спасибо, что прочитали меня:)

PS: я написалкод вручную, поэтому небольшая опечатка не является невозможной

Дэвид

1 Ответ

1 голос
/ 06 декабря 2011

Ваш запрос возвращает только людей. Как только вы получаете людей, вы вызываете getAddresses (), который лениво загружает адреса людей - все они. Короче говоря, запрос ограничивает набор возвращаемых людей, но поскольку он возвращает только людей, адреса загружаются с отложенным использованием другого запроса при доступе к набору адресов.

То, что вы хотите сделать, это вернуть людей с некоторыми из их адресов в одном запросе. Для этого вам нужно использовать ключевое слово fetch:

select distinct pers FROM Person pers 
join fetch pers.addresses address
where pers.matricule = :matricule                    
and address.date = :dateContract

Будьте очень осторожны: этот запрос возвращает неправильное представление сущности человека. Вы должны убедиться, что не изменили коллекцию адресов возвращенных лиц (хотя, поскольку сопоставление адресов сопоставлено ассоциацией Address.person, а каскад отсутствует, у вас не должно возникнуть проблем в этом конкретном случае).

...