Hibernate 为什么此枚举参数适用于单个字段而不适用于集合?
考虑以下JPA实体(实现为Hibernate 4.3.0): 如果改用字符串文字,则会得到结果。如果对非集合字段使用相同的参数策略,也会得到结果:Hibernate 为什么此枚举参数适用于单个字段而不适用于集合?,hibernate,jpa,jpql,Hibernate,Jpa,Jpql,考虑以下JPA实体(实现为Hibernate 4.3.0): 如果改用字符串文字,则会得到结果。如果对非集合字段使用相同的参数策略,也会得到结果: // Produces results queryString = "FROM MyEntity me WHERE 'BAD' MEMBER OF me.conditions"; things = JPA.em().createQuery(queryString, MyEntity.class).getResultList(); // Also p
// Produces results
queryString = "FROM MyEntity me WHERE 'BAD' MEMBER OF me.conditions";
things = JPA.em().createQuery(queryString, MyEntity.class).getResultList();
// Also produces results
queryString = "FROM MyEntity me WHERE me.myCondition = :condition";
things = JPA.em().createQuery(queryString, MyEntity.class).setParameter("condition", Condition.BAD).getResultList();
//So does this
String queryString = "from MyEntity me join me.conditions c where c = :condition";
List<MyEntity> things = JPA.em().createQuery(queryString, MyEntity.class).setParameter("condition", Condition.BAD).getResultList();
我认为Hibernate在使用参数时应该处理
EnumType.STRING
和EnumType.ORDINAL
的假设是错误的吗?至少,这是不一致的。当查询枚举字段而不是枚举集合时,填充参数起作用。我遗漏了什么?您的映射错误,因此结果不可预测
您错过了@ElementCollection
,仅在集合上使用@Enumerated
,这不是有效的映射
更新
看来问题出在别的地方了
您应该添加生成的SQL,以便我们可以获得更多信息
我尝试了一个等效的模式,查询运行良好:
return em.createQuery("from DocumentType x where :family member of x.families", DocumentType.class)
.setParameter("family", DocumentFamily.GENERIC)
.setMaxResults(5)
.getResultList();
而且
from DocumentType x where 'GENERIC' member of x.families
from DocumentType x join x.families f where f = :family
from DocumentType x join x.families f where f = 'GENERIC'
from DocumentType x join x.families f where f = it.shape.edea2.jpa.enums.DocumentFamily.GENERIC
生成的SQL查询有两种不同:
select ...
from ELEMENT_TYPE documentty0_
where documentty0_.DTYPE='DocumentType'
and ('GENERIC' in (
select families1_.FAMILY
from DOCUMENT_TYPE_FAMILY families1_
where documentty0_.ID=families1_.DOCUMENT_TYPE_ID))
limit 5
select ...
from ELEMENT_TYPE documentty0_
inner join DOCUMENT_TYPE_FAMILY families1_ on documentty0_.ID=families1_.DOCUMENT_TYPE_ID
where documentty0_.DTYPE='DocumentType'
and families1_.FAMILY='GENERIC'
limit 5
但有一点很奇怪:
from DocumentType x where it.shape.edea2.jpa.enums.DocumentFamily.GENERIC member of x.families
投掷
org.hibernate.QueryException: Unrecognized Hibernate Type for handling query constant (it.shape.edea2.jpa.enums.DocumentFamily.GENERIC); expecting LiteralType implementation or AttributeConverter
您使用的是哪个版本的Hibernate
我使用的是5.2.2以及您得到的答案,您可以通过实际调试来帮助自己。。。查看生成的SQL。。。看看JPA规范,它说在集合成员中不支持计算为可嵌入类型的表达式expressions@Neil斯托克顿,你凭什么认为我没有亲自尝试?在这个问题上,我试图在一个过于简单的实体中孤立和确定问题。我想我应该提到,第一个和第三个JPQL查询生成的SQL是相同的。至于JPA规范——枚举元素算是可嵌入的吗?我的印象是,Embeddebles本质上是被注释为Embeddeble的子类。人们只能对他们所展示的内容进行评论,这里的大多数人几乎没有调试,所以这始终是假设。至于您的问题,我可以在我使用的JPA提供程序(DataNucleus)中运行它(好的,一旦我添加了SELECT{alias}“make it valid JPQL)它创建了一个类似SQL的SELECT*FROM MYENTITY M internal JOIN MYENTITY_CONDITIONS B0 ON M.ID=B0.MYENTITY_ID其中B0.CONDITIONS_ELEMENT=
,因此工作正常。因此,问题出在JPA提供程序,而不是代码有趣的地方——当我编写JPQL以包含一个连接时,它会生成包含一个内部连接的SQL正如您所展示的,但是如果我使用
的成员,它将在
中使用。此外,由于参数化查询和文本查询生成的SQL之间的唯一区别是参数本身,我认为您是对的,这是我的提供程序(Hibernate)的方式正在处理参数。我希望我只是错误地使用了它。我也遇到了同样的问题,无法找到问题的根源,但能够将查询重写为枚举集合字段上的内部联接,在该字段中它与我所需的枚举值匹配,然后计算结果(>0表示集合确实包含所需的枚举值).我的错误。在制作示例时,我遗漏了该注释。注释仍会出现相同的行为。我将更新问题以反映这一点。使用4.3.0,如问题中所述。在集合上使用这样的联接与参数一起工作,因此它必须与@Neil Stockton所说的集合相关。尽管我仍然不知道为什么枚举会被认为是可嵌入的。@Indigenuity它一定是4.3.0中的一个bug,它已经很旧了(2013年12月)。您可以尝试运行4.3.11并检查该bug是否已被解决。我使用枚举的FQN得到Hibernate 5.3.7的“Unrecognized Hibernate Type”异常。使用字符串版本也可以。
from DocumentType x where 'GENERIC' member of x.families
from DocumentType x join x.families f where f = :family
from DocumentType x join x.families f where f = 'GENERIC'
from DocumentType x join x.families f where f = it.shape.edea2.jpa.enums.DocumentFamily.GENERIC
select ...
from ELEMENT_TYPE documentty0_
where documentty0_.DTYPE='DocumentType'
and ('GENERIC' in (
select families1_.FAMILY
from DOCUMENT_TYPE_FAMILY families1_
where documentty0_.ID=families1_.DOCUMENT_TYPE_ID))
limit 5
select ...
from ELEMENT_TYPE documentty0_
inner join DOCUMENT_TYPE_FAMILY families1_ on documentty0_.ID=families1_.DOCUMENT_TYPE_ID
where documentty0_.DTYPE='DocumentType'
and families1_.FAMILY='GENERIC'
limit 5
from DocumentType x where it.shape.edea2.jpa.enums.DocumentFamily.GENERIC member of x.families
org.hibernate.QueryException: Unrecognized Hibernate Type for handling query constant (it.shape.edea2.jpa.enums.DocumentFamily.GENERIC); expecting LiteralType implementation or AttributeConverter