У меня точно такая же проблема. После нескольких часов работы над проблемой, после отладки исходного кода Hibernate и повторной проверки примеров в книгах и спецификации JPA 2.0 я решил попробовать в EclipseLink.
Итак, я создал очень простой пример: сотрудник с картой номеров телефонов, где ключ — это тип телефона (домашний, рабочий, мобильный), а значение — номер телефона.
@ElementCollection(fetch=FetchType.EAGER)
@CollectionTable(name="emp_phone")
@MapKeyColumn(name="phone_type")
@Column(name="phone_num")
private Map<String, String> phoneNumbers;
Я мог убедиться, что это отлично работает с EclipseLink 2.1 и OpenJPA 2.1.0, но не работает в Hibernate 3.5.3, 3.6.1., 3.6.3.
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<Employee> criteria = builder.createQuery(Employee.class);
Root<Employee> employeeRoot = criteria.from(Employee.class);
criteria.select(employeeRoot);
MapJoin<Employee, String, String> phoneRoot = employeeRoot.joinMap("phoneNumbers");
criteria.where(builder.equal(phoneRoot.key(), "HOME"));
System.out.println(entityManager.createQuery(criteria).getResultList());
Я подумал, что если Criteria API не сработает, возможно, я смогу сделать это с помощью именованного запроса. Интересно, что Hibernate не поддерживает ключевые слова KEY, VALUE или ENTRY, поэтому запросы оказались некорректными.
http://opensource.atlassian.com/projects/hibernate/browse/HHH- 5396а>
Вот что запускается:
String query = "SELECT e FROM Employee e JOIN e.phoneNumbers p WHERE KEY(p) IN ('HOME')";
System.out.println(entityManager.createQuery(query, Employee.class).getResultList());
В спящем режиме он генерирует следующий SQL-запрос:
select
employee0_.id as id0_,
employee0_.name as name0_
from
Employee employee0_
inner join
emp_phone phonenumbe1_
on employee0_.id=phonenumbe1_.Employee_id
where
KEY(phonenumbe1_.phone_num) in (
'HOME'
)
Который явно деформирован.
Опять же, в EclipseLink и OpenJPA это работает.
Итак, очевидно, что-то не так с Hibernate. Я отправил сообщение об ошибке в Hibernate Jira Issue Tracker
https://hibernate.atlassian.net/browse/HHH-6103
И разместил вопрос на форуме пользователей Hibernate.
https://forum.hibernate.org/viewtopic.php?f=1&t=1010411
В конце концов мне пришлось решить проблему, используя набор встраиваемых объектов, содержащих те же записи, что и карта. Я был вынужден реализовать equals и hasHCode во встраиваемом коде, чтобы обеспечить такое же поведение.
person
Edwin Dalorzo
schedule
06.06.2011