programing

엔티티에서 Enum을 사용할 때 쿼리 생성 관련 문제

sourcejob 2022. 11. 23. 20:18
반응형

엔티티에서 Enum을 사용할 때 쿼리 생성 관련 문제

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

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

그리고.

@Enumerated(EnumType.STRING)
private Status status;

// usual accessors

다음과 같은 예외가 발생합니다.

예외 설명:쿼리 컴파일 중 오류 발생 [Question.count Approved:SELECT COUNT(q) FROM Question q WHERE q.status = 'APPROVED'], 줄 1, 열 47: 잘못된 열거 등식, 형식의 열거 값을 비교할 수 없습니다.[myCompnay.application.Status]type의 non-enum 값을 사용하여[java.lang.String]org.model에 있습니다.고집.internal.jpa.EntityManagerSetupImpl.deploy(EntityManagerSetupImpl.java:501)

이거 어떻게 고쳐야 돼요?

(완전 인정)를 사용하는 것이 좋을 것 같습니다.Status리터럴 값 대신 enum을 사용합니다.따라서 다음과 같습니다. (자세한 내용은Statusenum은 다음 위치에 있습니다.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;
}

저장소 필터링 메서드에 전달할 '필터'라는 래퍼 클래스가 있습니다.

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);
}

이것은 완벽하게 동작하지만, 아직 파악하지 못한 이상한 이유로 인해, 휴지 상태에서 SQL 디버깅을 활성화하고 바인더 로깅을 켜면 휴지 상태에서 이 식을 쿼리 변수에 바인딩하는 것을 볼 수 없습니다.

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

반응형