it-roy-ru.com

Spring Data JPA и запрос Exists

Я использую Spring Data JPA (с Hibernate в качестве моего JPA-провайдера) и хочу определить метод exists с приложенным HQL-запросом:

public interface MyEntityRepository extends CrudRepository<MyEntity, String> {

  @Query("select count(e) from MyEntity e where ...")
  public boolean existsIfBlaBla(@Param("id") String id);

}

Когда я запускаю этот запрос, я получаю Java.lang.ClassCastException: Java.lang.Long cannot be cast to Java.lang.Boolean.

Как должен выглядеть HQL-запрос, чтобы это работало? Я знаю, что мог бы просто вернуть значение Long и впоследствии проверить мой код Java, если count > 0, но этот обходной путь не должен быть необходимым, верно? 

36
Stefan Haberl

Я думаю, что вы можете просто изменить запрос, чтобы вернуть логическое значение как

@Query("select count(e)>0 from MyEntity e where ...")

PS: Если вы проверяете, существует на основе значения первичного ключа CrudRepository уже есть метод exists(id).

46
K. Siva Prasad Reddy

Spring Data JPA 1.11 теперь поддерживает проекцию exists при выводе запросов к репозиторию.

Смотрите документацию здесь .

В вашем случае будет работать следующее:

public interface MyEntityRepository extends CrudRepository<MyEntity, String> {  
    boolean existsByFoo(String foo);
}
108
Ankit Soni

Начиная с данных Spring 1.12, вы можете использовать запрос с помощью примера Functionnality, расширяя интерфейс QueryByExampleExecutor (JpaRepository уже расширяет его).
Тогда вы можете использовать этот запрос (среди прочих): 

<S extends T> boolean exists(Example<S> example);

Рассмотрим сущность MyEntity, которая в качестве свойства name вы хотите знать, существует ли сущность с таким именем, игнорируя регистр, тогда вызов этого метода может выглядеть следующим образом: 

//The ExampleMatcher is immutable and can be static I think
ExampleMatcher NAME_MATCHER = ExampleMatcher.matching()
            .withMatcher("name", GenericPropertyMatchers.ignoreCase());
Example<MyEntity> example = Example.<MyEntity>of(new MyEntity("example name"), NAME_MATCHER);
boolean exists = myEntityRepository.exists(example);
8
Stephane L

в моем случае это не сработало 

@Query("select count(e)>0 from MyEntity e where ...")

Вы можете вернуть его как логическое значение с помощью следующего

@Query(value = "SELECT CASE  WHEN count(pl)> 0 THEN true ELSE false END FROM PostboxLabel pl ...")
7
Runomu

Помимо принятого ответа, я предлагаю другую альтернативу . Используйте QueryDSL , создайте предикат и используйте метод exists(), который принимает предикат и возвращает логическое значение.

Одним из преимуществ QueryDSL является то, что вы можете использовать предикат для сложных предложений where.

1
Narasimha

Вы можете использовать выражение Case для возврата boolean в ваш запрос на выборку, как показано ниже.

@Query("SELECT CASE WHEN count(e) > 0 THEN true ELSE false END FROM MyEntity e where e.my_column = ?1")
0
Sahil Chhabra