Sự cố khi thực hiện truy vấn khi sử dụng Enum trong thực thể


83

Tôi có những thứ sau trong thực thể Câu hỏi:

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

@Enumerated(EnumType.STRING)
private Status status;

// usual accessors

Tôi nhận được ngoại lệ này:

Mô tả Ngoại lệ: Lỗi khi biên dịch truy vấn [Question.countApproved: SELECT COUNT(q) FROM Question q WHERE q.status = 'APPROVED'], dòng 1, cột 47: biểu thức bằng enum không hợp lệ, không thể so sánh giá trị enum của kiểu [myCompnay.application.Status]với giá trị không phải của kiểu enum [java.lang.String]. tại org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.deploy (EntityManagerSetupImpl.java:501)

Làm cách nào để sửa lỗi này?


bạn có đang sử dụng enum tùy chỉnh không? Bạn có thể cập nhật tài liệu để hiển thị tình trạng Trạng thái không?
Gonzalo Garcia Lasurtegui

Câu trả lời:


154

Tôi nghĩ bạn nên sử dụng Statusenum (đủ điều kiện) của mình thay vì giá trị theo nghĩa đen, vì vậy một cái gì đó như thế này: (giả sử Statusenum của bạn nằm trong com.myexamplegói)

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

Còn về một @Query thông thường JPA2 thì sao? Nó phàn nàn với: Giá trị cho thuộc tính chú thích Query.value phải là một biểu thức không đổi.
Stephane

2
Bạn @Queryđang nói về chú thích nào?
Piotr Nowicki

2
Điều này fully qualifiedquan trọng hơn như tôi nghĩ.
alexander

6
Ghi chú bên lề: Nó không hoạt động khi enum là một lớp bên trong của thực thể. Nếu điều này không hiệu quả với bạn, hãy đảm bảo rằng enum là tệp của riêng bạn!
evandongen

-5

4 năm kể từ bài viết đầu tiên, có một số phát triển. Sử dụng spring 4 và Hibernate 4 bây giờ có thể 'lừa' Hibernate bằng cách sử dụng biểu thức SpEL. Ví dụ:

Các enum:

package com.mycompany.enums

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

Đây là một lớp trình bao bọc được gọi là 'Bộ lọc' mà chúng ta sẽ chuyển sang phương pháp lọc kho lưu trữ.

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

 }

Cuối cùng, trong kho lưu trữ, bây giờ chúng ta có thể sử dụng lớp Bộ lọc làm tham số duy nhất và làm cho truy vấn dịch những gì có vẻ là hỗn hợp của các biểu thức chữ và biểu thức SpEL sang một đối tượng Trạng thái:

Kho lưu trữ:

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

Điều này hoạt động hoàn hảo, nhưng vì một số lý do kỳ lạ mà tôi chưa tìm ra, nếu bạn bật gỡ lỗi SQL trong Hibernate và bật ghi nhật ký chất kết dính, bạn sẽ không thể thấy Hibernate liên kết biểu thức này với các biến truy vấn.


Bạn không thấy nó trong số các ràng buộc biến vì hằng số đã được thay thế vào chuỗi truy vấn.
AbuNassar

-6

Vui lòng sử dụng thuộc tính dưới đây trong application.properties logging.level.org.hibernate.type.descriptor.sql.BasicBinder = TRACE

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.