У нас есть класс домена
@Entity
public class Gallery implements Serializable {
@Id
@GeneratedValue
private Long id;
@Enumerated(EnumType.ORDINAL)
private Status status;
// more attributes and getters/setters
}
Статус - это перечисление:
public enum Status {
OPEN (0, "offen"),
ACTIVE (1, "aktiv"),
INACTIVE (2, "inaktiv");
// attributes, constructor...
}
Затем у нас есть репозиторий Spring Data с запросом:
public interface GalleryRepository extends PagingAndSortingRepository<Gallery, Long> {
@Query("SELECT g FROM Gallery g WHERE (:status IS NULL or g.status = :status)")
public List<Gallery> findBySearchCriteria(@Param("status") Status status);
}
Назначение (:status IS NULL or g.status = :status)
заключается в том, что мы хотим, чтобы все данные, когда статус не задан, и получить только соответствующие данные при предоставлении статуса.
Мы получаем результаты этого запроса, когда статус имеет значение null, но мы не получаем никакого результата, если статус, например, ACTIVE, хотя есть данные в базе данных со статусом = ACTIVE.
Wenn мы удаляем :status IS NULL or
из запроса, мы получаем результаты, когда статус ACTIVE. Запрос выглядит так:
public interface GalleryRepository extends PagingAndSortingRepository<Gallery, Long> {
@Query("SELECT g FROM Gallery g WHERE (g.status = :status)")
public List<Gallery> findBySearchCriteria(@Param("status") Status status);
}
Я разрешаю записывать SQL и параметры, и когда я запускаю SQL (со :status IS NULL or
) вручную, я получаю ожидаемые результаты:
Hibernate: select gallery0_.id as id1_13_, gallery0_.institution_id as institut5_13_, gallery0_.internName as internNa2_13_, gallery0_.name as name3_13_, gallery0_.selectedShortId_id as selected6_13_, gallery0_.status as status4_13_ from Gallery gallery0_ where ? is null or gallery0_.status=?
2014-09-10 09:54:49,531 TRACE type.descriptor.sql.BasicBinder: binding parameter [1] as [VARBINARY] - ACTIVE
2014-09-10 09:54:49,531 TRACE type.descriptor.sql.BasicBinder: binding parameter [1] as [VARBINARY] - ACTIVE
2014-09-10 09:54:49,535 TRACE type.descriptor.sql.BasicBinder: binding parameter [2] as [VARBINARY] - ACTIVE
2014-09-10 09:54:49,535 TRACE type.descriptor.sql.BasicBinder: binding parameter [2] as [VARBINARY] - ACTIVE
SQL - это
select gallery0_.id as id1_13_, gallery0_.institution_id as institut5_13_, gallery0_.internName as internNa2_13_, gallery0_.name as name3_13_, gallery0_.selectedShortId_id as selected6_13_, gallery0_.status as status4_13_
from Gallery gallery0_
where 1 is null or gallery0_.status=1
Когда мы используем другие типы данных (например, String), конструкция (например (:name IS NULL or g.name = :name)
работает, как и ожидалось.
Есть ли что-то не так с этой конструкцией с перечислениями или это невозможно сделать в Spring Data/JPA?
Возможное обходное решение, которое мы имеем, заключается в том, чтобы писать в запросы, один со статусом и без него. В зависимости от того, является ли статус нулевым или нет, мы бы вызвали соответствующий метод в репозитории.
У меня была очень похожая проблема с параметрами Enum в весенних запросах данных и удалось решить ее, используя вместо этого строки в запросах (сохраняя сопоставления сущностей, как и с Enums):
public interface GalleryRepository extends PagingAndSortingRepository<Gallery, Long> {
@Query("SELECT g FROM Gallery g WHERE (:status IS NULL or g.status = :status)")
public List<Gallery> findBySearchCriteria(@Param("status") String status);
}
Вы пробовали просто создать запрос с использованием имени метода?
public interface GalleryRepository extends JpaRepository<Gallery, Long> {
public List<Gallery> findByStatus(Status status);
}