엔터티에서 Enum을 사용할 때 쿼리 작성 문제


86

질문 엔터티에 다음이 있습니다.

@NamedQuery(name = "Question.allApproved",
    query = "SELECT q FROM Question q WHERE q.status = 'APPROVED'")

@Enumerated(EnumType.STRING)
private Status status;

// usual accessors

이 예외가 발생합니다.

예외 설명 : 쿼리 [Question.countApproved : SELECT COUNT(q) FROM Question q WHERE q.status = 'APPROVED'], 1 행, 47 열 : 유효하지 않은 열거 형 등식 표현식을 컴파일하는 중 오류 가 발생했습니다. 유형의 열거 형 값을 유형 [myCompnay.application.Status]의 비 열거 형 값과 비교할 수 없습니다 [java.lang.String]. org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.deploy (EntityManagerSetupImpl.java:501)

이 문제를 어떻게 해결합니까?


사용자 정의 열거 형을 사용하고 있습니까? 상태 열거 형을 표시하도록 문서를 업데이트 할 수 있습니까?
Gonzalo Garcia Lasurtegui 2011

답변:


160

난 당신이 (완전한)를 사용한다고 생각 Status합니다 (가정 : 이런 일이, 그래서 대신 리터럴 값의 열거를 Status열거하는 인 com.myexample패키지)

@NamedQuery(name = "Question.allApproved", 
            query = "SELECT q 
                     FROM Question q 
                     WHERE q.status = com.myexample.Status.APPROVED").

JPA2 일반 @Query는 어떻습니까? 다음과 같이 불평합니다. 주석 속성 Query.value의 값은 상수 표현식이어야합니다.
Stephane 2014 년

2
무슨 @Query주석에 대해 말하고 있습니까?
Piotr Nowicki

2
이것은 fully qualified내가 생각했던 것보다 더 중요합니다.
알렉산더

9
참고 : 열거 형이 엔터티의 내부 클래스 일 때는 작동하지 않았습니다. 이것이 작동하지 않으면 열거 형이 자체 파일인지 확인하십시오!
evandongen

enum이 내부 클래스이면 @evandongen 어떤 해결책이 있습니까?
Raja aar

-5

초기 게시물 이후 4 년 동안 몇 가지 발전이 있습니다. Spring 4 및 Hibernate 4를 사용하면 이제 SpEL 표현식을 사용하여 Hibernate를 '트릭'할 수 있습니다. 예를 들면 :

열거 형 :

package com.mycompany.enums

public enum Status {
    INITIAL, PENDING, REJECTED, APPROVED, SHIPPED, DELIVERED, COMPLETE;
}

다음은 저장소 필터링 방법에 전달할 'Filter'라는 래퍼 클래스입니다.

package com.mycompany.enums

public class Filter implements Serializable {

    /** The id of the filtered item */
    private Integer id;
    /** The status of the filtered item */
    private Status status;
    // more filter criteria here...

    // getters, setters, equals(), hashCode() - omitted for brevity

    /**
     * Returns the name of the status constant or null if the status is null. This is used in the repositories to filter
     * queries by the status using a the SPEL (T) expression, taking advantage of the status qualified name. For example:
     * {@code :#{T(com.mycompany.enums.Status).#filter.statusName}}
     *
     * @return the status constant name or null if the status is null
     */
    public String getStatusName() {
        return null == status ? status : status.name();
    }

 }

마지막으로 저장소에서 이제 Filter 클래스를 단일 매개 변수로 사용하고 쿼리가 리터럴과 SpEL 표현식이 혼합 된 것처럼 보이는 것을 Status 객체로 변환 할 수 있습니다.

저장소 :

package com.mycompany.repository

@Repository
public interface OrderRepository extends CrudRepository<Order, Integer> {

    @Query("SELECT o from Order o "
            + "WHERE o.id = COALESCE(:#{#filter.id},o.id) "
            + "AND o.status = COALESCE(:#{T(com.mycompany.enums.Status).#filter.statusName},o.status)")
    public List<Order> getFilteredOrders(@Param(value = "filter") Filter filter);
}

이것은 완벽하게 작동하지만, 어떤 이상한 이유 때문에 아직 알아 내지 못했습니다. Hibernate에서 SQL 디버깅을 활성화하고 바인더 로깅을 켜면 Hibernate가이 표현식을 쿼리 변수에 바인딩하는 것을 볼 수 없습니다.


상수가 이미 쿼리 문자열로 대체 되었기 때문에 변수 바인딩에서 볼 수 없습니다.
AbuNassar

-6

application.properties에서 아래 속성을 사용하십시오. logging.level.org.hibernate.type.descriptor.sql.BasicBinder = TRACE

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.