У нас есть класс домена
@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)
заключается в том, что нам нужны все данные, когда статус не указан, и получить только соответствующие данные, когда статус задан.
Мы получаем результаты этого запроса, когда статус равен нулю, но мы не получаем никакого результата, если статус, например. АКТИВНО, хотя в базе есть данные со статусом=АКТИВНО.
Когда мы удаляем :status IS NULL or
из запроса, мы получаем результаты, когда статус АКТИВЕН. Запрос выглядит так
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?
Возможный обходной путь, который у нас есть, — писать в запросы, один со статусом, а другой без. В зависимости от того, является ли статус нулевым или нет, мы вызываем соответствующий метод в репозитории.