IT TIP

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

itqueen 2020. 11. 4. 21:05
반응형

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


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

@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)

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


나는 당신이 Status리터럴 값 대신에 (정규화 된) 열거 형 을 사용해야한다고 생각한다 . 그래서 다음과 같이 : (당신의 Status열거 형이 com.myexample패키지에 있다고 가정 )

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

초기 게시물 이후 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가이 표현식을 쿼리 변수에 바인딩하는 것을 볼 수 없습니다.


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

참고 URL : https://stackoverflow.com/questions/8217144/problems-with-making-a-query-when-using-enum-in-entity

반응형