Критерии гибернации, приводящие к тому, что продукт картезианца не так с HSQL: Spring Template? - PullRequest
0 голосов
/ 18 марта 2011

У меня есть две сущности Customer и Address.

Допустим, у Джона (Customer) есть пять адресов, тогда два приведенных ниже метода возвращают разные результаты

import org.springframework.orm.hibernate3.HibernateTemplate;

    @SuppressWarnings("unchecked")
    public List<Customer> getByNameCriteria(String firstName)
    {
        DetachedCriteria criteria = DetachedCriteria.forClass(Customer.class);
        criteria.add(Restrictions.eq("firstName", firstName));
        return (List<ReposTable>)hibernateTemplate.findByCriteria(criteria);
    }

    @SuppressWarnings("unchecked")
    public List<Customer> getByNameHSQL(String firstName)
    {
        return (List<Customer>) hibernateTemplate.findByNamedParam("from Customer t where t.firstName=:firstName","firstName",firstName);

    }

Фрагмент кода клиента

 List<Customer> allCustomers1 = rtRep.getByNameCriteria("John"); 

-> возвращает 5 строк: со списком адресов для каждой строки

 List<Customer> allCustomers2 = rtRep.getByNameHSQL("John"); 

-> возвращает 1 строку: со списком адресов

Клиент по адресу - это связь один ко многим следующим образом

@OneToMany(targetEntity=Address.class, fetch =  FetchType.EAGER, mappedBy="customer" )
@Cascade (value={CascadeType.SAVE_UPDATE })
private Set<Address> addresses = new HashSet<Address>();  

Вопрос :

  • Почему критерии ведут себя неправильно, он выдает декартово запрос продукта, где HSQL выдает два отдельных запроса: один для Customer и один для Address и показывает ожидаемый результат. 1030 *

  • Имеет ли это отношение к: setResultTransformer, Различным проблемам корневых сущностей, пожалуйста, уточните.

Спасибо

1 Ответ

4 голосов
/ 18 марта 2011

Это хорошо известное поведение (хотя я не могу найти источник, где он четко определен как действительный).

Вам необходимо применить преобразователь результатов

criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

или настроить Hibernateчтобы получить ваши отношения с SELECT:

@OneToMany(targetEntity=Address.class, fetch =  FetchType.EAGER, mappedBy="customer" )    
@Cascade (value={CascadeType.SAVE_UPDATE })
@Fetch(FetchMode.SELECT)
private Set<Address> addresses = new HashSet<Address>();   

Обратите внимание, что при некоторых обстоятельствах (особенно если вы ожидаете, что запрос выдаст много Customers, а у каждого Customer есть несколько Address es)запрос с JOIN может быть предпочтительным по соображениям производительности.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...