为什么这个枚举参数适用于单个字段而不适用于集合?

时间:2017-01-12 22:57:44

标签: hibernate jpa jpql

考虑以下JPA实体(实现是Hibernate 4.3.0):

find_overlaping(rectangle)

当我使用enum参数运行以下查询时,我得到0结果(无错误):

@Entity
public class MyEntity {

    @Id
    protected long myEntityId;

    @Enumerated(EnumType.STRING)
    public Condition myCondition = Condition.BAD;

    @Enumerated(EnumType.STRING)
    @ElementCollection
    public Set<Condition> conditions = new HashSet<Condition>();

    public enum Condition {
        GOOD, FAIR, BAD, SOL
    }
}

此查询生成以下SQL:

//Produces no results
String queryString = "FROM MyEntity me WHERE :condition MEMBER OF me.conditions";
List<MyEntity> things = JPA.em().createQuery(queryString, MyEntity.class).setParameter("condition", Condition.BAD).getResultList();

如果我使用字符串文字,我会得到结果。如果我对非集合字段使用相同的参数策略,我也会得到结果:

select myentity0_.myentityid as myentity1_38_, myentity0_.mycondition as mycondit2_38_ 
from MyEntity myentity0_ 
where ? in (
    select conditions1_.conditions 
    from MyEntity_conditions conditions1_ 
    where myentity0_.myentityid=conditions1_.MyEntity_myEntityId)

这些查询产生以下SQL:

// 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在使用参数时应该处理select myentity0_.myentityid as myentity1_38_, myentity0_.mycondition as mycondit2_38_ from MyEntity myentity0_ where 'BAD' in ( select conditions1_.conditions from MyEntity_conditions conditions1_ where myentity0_.myentityid=conditions1_.MyEntity_myEntityId) select myentity0_.myentityid as myentity1_38_, myentity0_.mycondition as mycondit2_38_ from MyEntity myentity0_ where myentity0_.mycondition=? select myentity0_.myentityid as myentity1_38_, myentity0_.mycondition as mycondit2_38_ from MyEntity myentity0_ inner join MyEntity_conditions conditions1_ on myentity0_.myentityid=conditions1_.MyEntity_myEntityId where conditions1_.conditions=? EnumType.STRING,这是错误的吗?至少,它是不一致的。在查询枚举字段而不是枚举集合时,填充参数有效。我错过了什么?

1 个答案:

答案 0 :(得分:2)

您的映射错误,因此结果无法预测。

您错过了@ElementCollection,只使用了@Enumerated Collection,这不是有效的映射。

<强>更新

似乎问题出在其他地方。

您应该添加生成的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