Spring Data has a great declarative way of defining queries, called derived queries. Suppose you have a Person class with an email field. Then you can define the following method in a Repository interface:

public interface PersonRepository extends JpaRepository<Person,Long>{
  List<Person> findByEmail(String email);
}

Spring derives the query based on the method name, in this case a query to retrieve all persons with a given value for the email field.

As you can see, the method returns a List. If you want to process all Persons, that is ok. But sometimes you want to know ‘does a row with this particular value exist?’.

One way to do this is as follows:

if(!personRepository.findByEmail("test@mail.com").isEmpty()){
  //do something if a person with the test email already exists in the repository
}

Personally, the additional call to the isEmpty() method is a bit too much for me. This can be solved as follows:

public interface PersonRepository extends JpaRepository<Person,Long>{
  @Query("SELECT CASE WHEN COUNT(c) > 0 THEN true ELSE false END FROM Person p WHERE p.email = :email")
    boolean existsByEmail(@Param("email") String email);
}

Now the method does return a boolean, but then again we now have this ugly case in the query. Is there a better way?

Yes, there is - but it is very well hidden in one of the appendices of the spring data docs. A query can in fact return a boolean. As always, there is a disclaimer stating

consult the store-specific documentation for the exact list of supported return types, because some types listed here might not be supported in a particular store.

So we can just update the very first code snippet to:

public interface PersonRepository extends JpaRepository<Person,Long>{
  boolean findByEmail(String email); //now returns a boolean instead of a List<Person>
}