Java JPA“使用枚举时编译查询时出错”

时间:2010-11-16 15:14:52

标签: java jpa enums

以下JPA查询无法编译:

@NamedQuery(name = "PSA.findBySourceSystem", 
    query = "SELECT p FROM PSA p WHERE p.sourceSystem.id = :sourceSystemId")

p.sourceSystem是以下枚举:

public enum SourceSystem {
    FIRST(3, "ABC"), SECOND(9, "DEF"), THIRD(17, "GHI");

    private int id;
    private String code;
    ...
}

并映射到PSA的 base 类:

public class PsaBase implements Serializable {
    @Column(name = "sourceSystemId")
    @Enumerated(EnumType.ORDINAL)
    protected SourceSystem sourceSystem;
    ...
}

如果我用更好的方式替换查询中的p.sourceSystem.id,查询将编译并运行正常。

提前感谢您的帮助。

1 个答案:

答案 0 :(得分:2)

它不应该编译。

在将其作为查询参数传递之前,您必须手动解析所需的枚举值:

@NamedQuery(name = "PSA.findBySourceSystem",  
    query = "SELECT p FROM PSA p WHERE p.sourceSystem = :sourceSystem") 

public enum SourceSystem { 
    ... 
    private static Map<Integer, SourceSystem> valuesById = new HashMap<Integer, SourceSystem>();
    static {
        for (SourceSystem s: values()) 
            valuesById.put(s.id, s);
    }
    public static SourceSystem findById(int id) {
        return valuesById.get(id);
    }
} 

em.createNamedQuery("PSA.findBySourceSystem")
    .setParameter("sourceSystem", SourceSystem.findById(sourceSystemId));

修改 由于sourceSystem注释为@Enumerated(EnumType.ORDINAL),因此它作为相应枚举值的序号存储在数据库中,因此FIRST存储为0。 JPA不直接支持使用枚举值的任意字段在数据库中标识它。如果您的数据库模式假定,您可以执行以下技巧来将对象的状态与数据库模式分离:

public class PsaBase implements Serializable { 
    protected SourceSystem sourceSystem; 

    @Column(name = "sourceSystemId") 
    public Integer getSourceSystemId() {
        return sourceSystem.getId();
    }

    public void setSourceSystemId(Integer id) {
        this.sourceSystem = SourceSystem.findById(id);
    }
    ... getter and setter of sourceSystem with @Transient ...
}