Java JPA "Ошибка компиляции запроса", когда он использует перечисление - PullRequest
1 голос
/ 16 ноября 2010

Следующий запрос 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;
    ...
}

и отображается в base PSAclass:

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

Запрос компилируется и работает нормально, если я заменю p.sourceSystem.id в запросе чем-то более мягким.

Заранее благодарю за любую помощь.

1 Ответ

2 голосов
/ 16 ноября 2010

Не должно компилироваться.

Необходимо разрешить требуемое значение перечисления вручную перед передачей его в качестве параметра запроса:

@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 напрямую не поддерживает использование произвольного поля значения enum для его идентификации в базе данных.Если ваша схема базы данных предполагает это, вы можете выполнить следующую уловку, чтобы отделить состояние вашего объекта от схемы базы данных:

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 ...
} 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...