首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >HIBERNATE - JPA2 - H2 - Querying @ElementCollections HashMap by key

HIBERNATE - JPA2 - H2 - Querying @ElementCollections HashMap by key
EN

Stack Overflow用户
提问于 2011-06-06 07:53:26
回答 1查看 9K关注 0票数 3

我正在使用hibernate-EntityManager3.6.4,using和h2数据库1.3.155

我在用H2Dialect。

我在通过@ElementCollection中的元素过滤记录时遇到了问题。这是我的实体

代码语言:javascript
复制
@Entity
public class Item {
  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  @MapKeyColumn(name="name", length=50)
  @Column(name="value", length=100)
  protected Map<String, String> attributes;
  /*  etc.  */
}

下面是我的问题:

代码语言:javascript
复制
Item item = em.createQuery("FROM Item i JOIN i.attributes a WHERE KEY(a)='myAttrName'").getSingleResult();

以下是错误消息:

代码语言:javascript
复制
4971 [main] WARN org.hibernate.util.JDBCExceptionReporter - SQL Error: 90022, SQLState: 90022
4971 [main] ERROR org.hibernate.util.JDBCExceptionReporter - Function "KEY" not found; SQL statement:
Exception in thread "main" javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: could not execute query

这非常奇怪,因为在文档here中提供了函数KEY()和VALUE()

我是否遗漏了一些配置?有什么想法吗?

提前感谢

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2011-06-06 10:39:26

我也有同样的问题。在处理这个问题几个小时之后,在调试Hibernate源代码之后,在反复检查书籍和JPA2.0规范中的示例之后,我决定在EclipseLink中尝试一下。

因此,我创建了一个非常简单的示例:一个员工有一个电话号码映射,其中键是电话类型(家庭、办公室、移动电话),值是电话号码。

代码语言:javascript
复制
@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中失败

代码语言:javascript
复制
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

下面是运行的内容:

代码语言:javascript
复制
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());

在hibernate中,它生成以下SQL查询:

代码语言:javascript
复制
   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问题跟踪器中提交了一个bug

https://hibernate.atlassian.net/browse/HHH-6103

并在Hibernate用户论坛上发布了这个问题

https://forum.hibernate.org/viewtopic.php?f=1&t=1010411

最后,我不得不使用包含与map相同的条目的可嵌入对象集合来解决这个问题。为了满足同样的行为,我不得不在embeddable中实现equals和hasHCode。

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6246735

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档